我有一个使用 avr-objcopy 反汇编的二进制文件。中断向量表如下所示:
00000000 : ; VECTOR TABLE 0: 13 c0 rjmp .+38 ; 0x28, RESET 2: b8 c1 rjmp .+880 ; 0x374, INT0 4: fd cf rjmp .-6 ; 0x0 6: fc cf rjmp .-8 ; 0x0 8: fb cf rjmp .-10 ; 0x0 a: fa cf rjmp .-12 ; 0x0 c: f9 cf rjmp .-14 ; 0x0 e: f8 cf rjmp .-16 ; 0x0 10: f7 cf rjmp .-18 ; 0x0 12: c7 c1 rjmp .+910 ; 0x3a2, TIMER1 OVF 14: f5 cf rjmp .-22 ; 0x0 16: f4 cf rjmp .-24 ; 0x0 18: f3 cf rjmp .-26 ; 0x0 1a: f2 cf rjmp .-28 ; 0x0 1c: 2b c2 rjmp .+1110 ; 0x474, ADC conversion complete 1e: f0 cf rjmp .-32 ; 0x0 20: ef cf rjmp .-34 ; 0x0 22: ee cf rjmp .-36 ; 0x0 24: ed cf rjmp .-38 ; 0x0 26: 00 00 nop ; START 28: f8 94 cli (snip)
我想通过一些修改重新组装该文件。我通过删除前两列对其进行了重新格式化,使其成为常规的汇编文件。即:
.org 0 rjmp .+38 ; 0x28, RESET rjmp .+880 ; 0x374, INT0 (snip)
但是,当我运行时
$ avr-as -mmcu=atmega8 test.asm
然后反汇编生成的文件。 (使用 objcopy -S a.out)输出如下所示:
00000000 : 0: 00 c0 rjmp .+0 ; 0x2 2: 00 c0 rjmp .+0 ; 0x4 4: 00 c0 rjmp .+0 ; 0x6 6: 00 c0 rjmp .+0 ; 0x8 8: 00 c0 rjmp .+0 ; 0xa a: 00 c0 rjmp .+0 ; 0xc c: 00 c0 rjmp .+0 ; 0xe e: 00 c0 rjmp .+0 ; 0x10 10: 00 c0 rjmp .+0 ; 0x12 12: 00 c0 rjmp .+0 ; 0x14 14: 00 c0 rjmp .+0 ; 0x16 16: 00 c0 rjmp .+0 ; 0x18 18: 00 c0 rjmp .+0 ; 0x1a 1a: 00 c0 rjmp .+0 ; 0x1c 1c: 00 c0 rjmp .+0 ; 0x1e 1e: 00 c0 rjmp .+0 ; 0x20 20: 00 c0 rjmp .+0 ; 0x22 22: 00 c0 rjmp .+0 ; 0x24 24: 00 c0 rjmp .+0 ; 0x26 26: 00 00 nop 28: f8 94 cli (snip)
那么我怎样才能让 avr-as 尊重 PC 相对跳转呢?
最佳答案
我找到了答案!
我正在组装但没有链接。因此汇编器用 .+0 填充所有相对跳转/调用/分支。
为了解决这个问题,我需要创建一个名为 linker.x 的自定义链接器脚本,其中包含以下内容:
SECTIONS { . = 0x0; .text : { *(.text) } }
This tells the linker to start the .text section at address 0.
Then I could link the code using:
$ avr-ld -mavr4 -Tlinker.x a.out -o output.o
使用上述命令链接后,所有 .+0 都已填写正确的值!
这样做的原因是,在链接阶段之前,as/gcc 不知道二进制文件中还将包含什么内容。它是一个链接器,它获取所有单独的目标文件并将它们组合成一个。因此,如果链接器阶段从未运行,则无法用绝对跳转来填充相对跳转。
AVR 的汇编器负责汇编和链接。但 gnu 汇编器更通用,因此您需要单独链接。
关于assembly - 如何使用 AVR 的 gnu 汇编器相对于 PC 跳转?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1761197/