RIP 相对寻址的 GAS 语法如下所示symbol + current_address
(RIP),但这实际上意味着symbol
关于 RIP
.
数字文字存在不一致:
-
[rip + 10]
或美国电话电报公司10(%rip)
表示该指令结束后 10 个字节
-
[rip + a]
或美国电话电报公司a(%rip)
意思是计算一个rel32
位移达到a
, notRIP + 符号值。 (气体手册记录这个 https://sourceware.org/binutils/docs/as/i386_002dMemory.html特别解释)
-
[a]
或美国电话电报公司a
是绝对地址,采用disp32寻址方式。 OS X 不支持此功能,其中映像基址始终位于低 32 位之外。 (或者对于mov https://www.felixcloutier.com/x86/mov到/从 al/ax/eax/rax,64 位绝对值moffs
编码可用,但您不希望这样)。
Linux 位置相关的可执行文件do将静态代码/数据放在虚拟地址空间的低 31 位 (2GiB) 中,因此您可以/应该使用mov edi, sym
在那里,但在 OS X 上你最好的选择是lea rdi, [sym+RIP]
如果您需要寄存器中的地址。无法使用 Mac x86 程序集将 .data 中的变量移动到寄存器 https://stackoverflow.com/questions/50205129/unable-to-move-variables-in-data-to-registers-with-mac-x86-assembly.
(在 OS X 中,惯例是 C 变量/函数名称前面加上_
在汇编中。在手写汇编中你不需要have对您不想从 C 访问的符号执行此操作。)
NASM 在这方面就不那么令人困惑了:
-
[rel a]
表示 RIP 相对寻址[a]
-
[abs a]
means [disp32]
.
-
default rel
or default abs
设置用途[a]
。默认值是(不幸的是)default abs
,所以你几乎总是想要一个default rel
.
示例为.set
符号值与标签
.intel_syntax noprefix
mov dword ptr [sym + rip], 0x11111111
sym:
.equ x, 8
inc byte ptr [x + rip]
.set y, 32
inc byte ptr [y + rip]
.set z, sym
inc byte ptr [z + rip]
gcc -nostdlib foo.s && objdump -drwC -Mintel a.out
(在 Linux 上;我没有 OS X):
0000000000001000 <sym-0xa>:
1000: c7 05 00 00 00 00 11 11 11 11 mov DWORD PTR [rip+0x0],0x11111111 # 100a <sym> # rel32 = 0; it's from the end of the instruction not the end of the rel32 or anywhere else.
000000000000100a <sym>:
100a: fe 05 08 00 00 00 inc BYTE PTR [rip+0x8] # 1018 <sym+0xe>
1010: fe 05 20 00 00 00 inc BYTE PTR [rip+0x20] # 1036 <sym+0x2c>
1016: fe 05 ee ff ff ff inc BYTE PTR [rip+0xffffffffffffffee] # 100a <sym>
(拆解.o
with objdump -dr
将向您显示链接器不需要填充任何重定位,它们都是在汇编时完成的。)
请注意,仅.set z, sym
得出了关于计算的结果。x
and y
最初来自纯数字文字,而不是标签,所以即使指令本身使用[x + RIP]
,我们仍然得到[RIP + 8]
.
(仅限 Linux 非 PIE):绝对地址8
字。 RIP,您需要 AT&T 语法incb 8-.(%rip)
。我不知道如何在GAS中写这个intel_syntax
; [8 - . + RIP]
被拒绝Error: invalid operands (*ABS* and .text sections) for '-'
.
当然,在 OS X 上无论如何你都不能这样做,除非图像库范围内的绝对地址除外。但可能没有重定位可以保存要为 32 位 rel32 计算的 64 位绝对地址。
Related:
-
如何将函数或标签的地址加载到寄存器中 https://stackoverflow.com/questions/57212012/how-to-load-address-of-function-or-label-into-register-in-gnu-assemblerAT&T 版本
-
x86-64 Linux 中不再允许使用 32 位绝对地址? https://stackoverflow.com/questions/43367427/32-bit-absolute-addresses-no-longer-allowed-in-x86-64-linuxPIE 与非 PIE 可执行文件,当您have使用与位置无关的代码。