我正在使用GNU AS作为汇编程序,我正在尝试编写与位置无关的二进制文件,并且在编写外部符号的PC相对地址时遇到了一些问题.Normaly是一个相对地址
adr r0, symbol
Run Code Online (Sandbox Code Playgroud)
但这仅适用于汇编文件中同一部分中定义的符号.另一种加载符号的方法是
ldr r0, =symbol
Run Code Online (Sandbox Code Playgroud)
它将符号的绝对地址存储在一个常量中,并从那里加载它的pc.所以你得到这样的代码:
48: e59f0008 ldr r0, [pc, #8] ; 58 <text+0xc>
...
58: 00000008 .word 0x00200018
58: R_ARM_ABS32 symbol
Run Code Online (Sandbox Code Playgroud)
但我需要的是一个R_ARM_REL32链接器引用.
我想出的是这段代码:
tmp1: ldr r0, [pc, #tmp2 - tmp1 - 8]
ldr r0, [pc, r0]
tmp2: .word symbol - tmp1
Run Code Online (Sandbox Code Playgroud)
这会产生:
0000003c <tmp1>:
3c: e59f0000 ldr r0, [pc] ; 44 <tmp2>
40: e79f0000 ldr r0, [pc, r0]
00000044 <tmp2>:
44: 00000008 .word 0x00000008
44: R_ARM_REL32 symbol
Run Code Online (Sandbox Code Playgroud)
我几乎可以将它放入一个宏中,因此它可以重用于我需要的任何符号.除了我不知道如何告诉汇编程序tmp2需要转到常量块而不是在代码中间结束.
但是在GNU AS中是不是已经存在一些现有的语法或宏?
不要明确定义该词。怎么样:
.text
1: ldr r0, =symbol-1b
ldr r0, [pc, r0]
Run Code Online (Sandbox Code Playgroud)
这给出了类似的东西:
[~] dev% ~/ellcc/bin/ecc-objdump -d test.o
test.o: file format elf32-bigarm
Disassembly of section .text:
00000000 <.text>:
0: e59f0000 ldr r0, [pc] ; 8 <.text+0x8>
4: e79f0000 ldr r0, [pc, r0]compatable
8: 00000008 .word 0x00000008
Run Code Online (Sandbox Code Playgroud)
使用正确的重新定位:
RELOCATION RECORDS FOR [.text]:
OFFSET TYPE VALUE
00000008 R_ARM_REL32 symbol
Run Code Online (Sandbox Code Playgroud)
重新定位的单词将放置在代码后面的某个位置。
警告:我使用 clang 的集成汇编器组装了它。我假设 GNU as 会处理同样的事情,因为它们试图兼容 bug。
[编辑] 不幸的是,正如 Jester 在评论中提到的,这不适用于 GNU as。我认为我从未见过 clang 的集成汇编器做了 GNU 汇编器以前无法处理的事情的例子。