我正在使用GNU AS汇编器,试图编写一个位置无关的二进制文件,但在编写外部符号的PC相对地址时遇到了一些问题。通常情况下,可以使用以下代码加载相对地址:
adr r0, symbol
但是这仅适用于在汇编文件中定义在同一节中的符号。加载符号的另一种方法是
ldr r0, =symbol
该代码将符号的绝对地址存储在常量中,并从那里以PC相对方式加载它。 因此,您可以获得以下代码:
48: e59f0008 ldr r0, [pc, #8] ; 58 <text+0xc>
...
58: 00000008 .word 0x00200018
58: R_ARM_ABS32 symbol
但我需要的是R_ARM_REL32链接器引用。
我想到的代码是:
tmp1: ldr r0, [pc, #tmp2 - tmp1 - 8]
ldr r0, [pc, r0]
tmp2: .word symbol - tmp1
这将产生以下结果:
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
我几乎可以将它放入宏中,以便于我需要的任何符号重用。但是,我不知道如何告诉汇编程序tmp2需要进入常量块而不是出现在代码中间。
但是,在GNU AS中是否已经存在某些现有的语法或宏来处理这个问题呢?
adrl
吗?这应该允许更大的引用,并且您可以使用-fwhole-program
。我认为在'C'中,如果没有某种重定位(如plt、glt等),您无法做到这一点。通常,'C'认为您可以像访问全局变量等一样做事情。对于ARM ABI,*.text和.data*可能相距很远,编译器需要支持此功能。还有这个问题。话虽如此,u-boot使用'sb'来实现这一点。 - artless noise