kro*_*lar 2 assembly avr gnu-assembler disassembly relative-addressing
我有一个二进制文件,我使用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-尊重PC相对跳跃?
我找到了答案!
我正在组装但没有连接.所以汇编程序用.+ 0填充所有相对跳转/调用/分支.
为了解决这个问题,我需要创建一个名为linker.x的自定义链接描述文件,其中包含以下内容:
SECTIONS
{
. = 0x0;
.text : { *(.text) }
}
这告诉链接器在地址0处启动.text部分.
然后我可以使用以下代码链接代码:
$ avr-ld -mavr4 -Tlinker.x a.out -o output.o
Run Code Online (Sandbox Code Playgroud)
使用上面的命令链接后,所有.+ 0都填入了正确的值!
之所以这样,是因为直到链接阶段,因为/ gcc不知道还有哪些内容会包含在二进制文件中.链接器接收所有单个目标文件并将它们合并为一个.因此,如果链接器阶段永远不会运行,则无法用绝对跳转填充相对跳转.
AVR的汇编程序可以进行组装和链接.但是gnu汇编程序更通用,因此您需要单独链接.