我有一个带有Attiny45固件的HEX文件。我想要做的是提取其中编码的某种公式。我进行了一些研究(大部分是为了找出“不可能”等),但我决定尝试一下,因为研究的其他部分向我展示了大多数提出此类问题的人几乎不知道什么是HEX文件。

这篇文章的目的不是要从HEX文件中拿出明亮的C代码,而是要建立关于该主题的扎实知识。我知道编译器在执行其工作时可能会使我自己的工作更加困难,但是为了使CPU能够执行代码,需要遵循某种结构(也许是原始结构)。

因此,我坐在办公桌上并编写了一个Python小工具以帮助我进行此过程。它加载了HEX文件,并且我可以交互地向其中添加信息。这是到目前为止我得到的:

HEX文件的第一行说:

: 02 0000 04 0000 FA


该工具可以执行以下操作:

:       --> MARK
02      --> RECORD LENGTH
0000    --> LOAD OFFSET
04      --> RECORD TYPE (EXTENDED LINEAR ADDRESS RECORD)
0000    --> DATA
FA      --> CHECKSUM


这行似乎是建议告诉代码应放置的初始地址为0x0000的提议。

其次,下一行显示:

: 20 0000 00 34C0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF50C07EEE7EB9 51


该工具将其解码为:

:    --> MARK
20   --> LENGHT OF THE RECORD
0000 --> OFFSET
00   --> RECORD TYPE (00 -> DATA RECORD) 34C0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF50C07EEE7EB9 (ACTUAL DATA)
51   --> CHECKSUM


在这里有趣,问题开始了。




我在任何地方都找不到ATTiny45的内存映射。我认为它应该在数据表或说明手册中的某处。据我所知,在0x0000处存在中断向量(数据表第49页),第一个是复位向量。因此,AVR为低位字节序,指令为16位宽,因此我可以解码出复位向量包含值0xC034。使用指令集,我发现0xC034是:

rjump 0x034


这是正确的吗?


继续这种思路,前面指出的同一行表明某些中断向量的值0xFFFF,这使我感到惊讶,但似乎没有问题,因为可能会禁用它们。具有工作值的唯一其他向量是USI_OVF_ISR,它等于0xC050。因此,根据之前提出的想法,这表示USI_OVF_ISR具有以下说明:

rjump 0x050


这是否还正确?


如果复位向量指向0x034,则表示程序将从0x034开始运行。下一行

: 20 0020 00 7FE77FB9B89A089570EE7EB95FB9B89A08957EEE7EB9B898089570EE7EB9B898 22


显示0x0340xB898,这是将要执行的第一条指令。

这是正确的吗?



#1 楼



似乎几乎是正确的,因为数据手册在第8.1章“复位AVR”中进行了说明: –相对
跳转–复位处理例程的指令


然而,第202页-指令集摘要-像这样解释RJMP: br />
这暗示着地址RJMP处的PC=0k=0x34跳到了地址0x35

,数据表似乎没有操作码表来确认C0是确实是一个RJMP

第5.1章还说


ATtiny25 / 45/85包含2/4 / 8K字节片内输入-System可重编程闪存,用于存储程序。由于所有AVR指令的宽度均为16或32位,因此Flash的格式为1024/2048/4096 x16。


,第9章显示了表格(第48页)其中包含RJMP指令的示例,这些指令虽然需要2个字节,但每个都打包到一个地址中。从偏移量0开始,并使用15个复位矢量(每个复位矢量均为16位宽),程序从地址0x0F开始。因此,地址空间似乎每个地址分为16位块,而不是8位字节,这意味着您必须将地址加倍才能在十六进制数组中获得适当的字节索引。

对我来说似乎不正确,因为PC是0D(在十六进制字节中偏移1A)和r=50,所以RJMP应该跳到0D+50+1 = 5E或在十六进制字节中偏移BC2*0x5E)。该地址表示16位字,然后从操作码选项卡中添加+1,您可能应该查看0x35*2=0x6A以查找要执行的第一条指令。