如何使用AVR的gnu汇编程序相对于PC跳转?

时间:2009-11-19 06:04:39

标签: assembly relative avr disassembly gas

我有一个二进制文件,我使用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相对跳跃?

2 个答案:

答案 0 :(得分:6)

我找到了答案!

我正在组装但没有连接。所以汇编程序用。+ 0填充所有相对跳转/调用/分支。

要解决此问题,我需要创建一个名为linker.x的自定义链接描述文件,其中包含以下内容:

SECTIONS
{
  . = 0x0;
  .text : { *(.text) }
}

这告诉链接器在地址0处启动.text部分。

然后我可以使用:

链接代码
$ avr-ld -mavr4 -Tlinker.x a.out -o output.o

使用上面的命令链接后,所有的。+ 0都填入了正确的值!

之所以这样,是因为直到链接阶段,因为/ gcc不知道其他内容将包含在二进制文件中。链接器接收所有单个目标文件并将它们合并为一个。因此,如果链接器阶段永远不会运行,则无法用绝对跳转填充相对跳转。

AVR的汇编程序可以进行组装和链接。但是gnu汇编程序更通用,所以你需要单独链接。

答案 1 :(得分:0)

我假设rjmp PC+2在avr-as中不起作用?这就是我在AVR Studio中的表现......