assembly - 如何使用 AVR 的 gnu 汇编器相对于 PC 跳转?

标签 assembly avr disassembly gnu-assembler 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-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/

相关文章:

assembly - bootsector编程中无限跳转有什么用

c++ - ebp + 6 而不是 JIT 编译器中的 +8

c - AVR C 编程 - 为什么 while 循环之后的代码没有执行?

java - 了解 Dalvik 代码的反汇编?

java - 了解 Java 热点 JIT 生成的用于 float 测试的代码

assembly - 在 x86 汇编中实现 160x100 模式

c - 理解指针和汇编中的类型转换

c - 访问 Arduino/AVR 上 PROGMEM 中的各个字节

arduino - 使用 Ada 对 Arduino 进行编程

windows - 如何在 x64 VC++ 编译器上禁用 FPO 优化