Cir*_*四事件 2 assembly x86-64 gnu-assembler nasm elf
作为一个具体的例子,在GAS 2.24上移动地址:
mov $s, %eax
s:
Run Code Online (Sandbox Code Playgroud)
后:
as --64 -o a.o a.S
objdump -Sr a.o
Run Code Online (Sandbox Code Playgroud)
使用零扩展:
0000000000000000 <s-0x5>:
0: b8 00 00 00 00 mov $0x0,%eax
1: R_X86_64_32 .text+0x5
Run Code Online (Sandbox Code Playgroud)
但内存访问:
mov s, %eax
s:
Run Code Online (Sandbox Code Playgroud)
编译以签署扩展名:
0000000000000000 <s-0x7>:
0: 8b 04 25 00 00 00 00 mov 0x0,%eax
3: R_X86_64_32S .text+0x7
Run Code Online (Sandbox Code Playgroud)
在这种特定情况下,或者一般情况下,是否有理由使用?我不明白汇编程序如何能够对任何一种情况做出更好的假设.
NASM 2.10.09仅R_X86_64_32用于上述两种情况.更新:在2.11之后的一个边缘nasm commit 6377180产生相同的Gas输出,这看起来像Ross提到的一个bug.
我已经解释了我认为我理解的内容R_X86_64_32S:https://stackoverflow.com/a/33289761/895245
不同之处在于符号的允许地址s.在使用R_X86_64_32的第一种情况下,符号必须在0x00000000'00000000到0x00000000'FFFFFFFF的范围内.在使用R_X86_64_32S的第二种情况下,符号的地址必须在0xFFFFFFFF'80000000和0x00000000'7FFFFFFF之间.如果s最终的地址超出这些范围,则链接器将给出错误.
这对应于CPU如何将s编码的32位值解释为两个指令.在第一条指令中,它是一个立即操作数,32位值被零扩展到RAX中.在第二条指令中,32位值是存储器操作数中的位移,因此符号扩展为64位地址.
NASM不应该对第二条指令使用无符号R_X86_64_32重定位.这不是一个更好的问题,使用R_X86_64_32这里是不正确的.NASM允许地址为s0x00000000'80000000,但CPU最终会访问0xFFFFFFFF'80000000.