举个具体的例子,在 GAS 2.24 上,移动地址:
mov $s, %eax
s:
After:
as --64 -o a.o a.S
objdump -Sr a.o
使用零扩展:
0000000000000000 <s-0x5>:
0: b8 00 00 00 00 mov $0x0,%eax
1: R_X86_64_32 .text+0x5
但是内存访问:
mov s, %eax
s:
编译为签名扩展:
0000000000000000 <s-0x7>:
0: 8b 04 25 00 00 00 00 mov 0x0,%eax
3: R_X86_64_32S .text+0x7
在这种特定情况下或一般情况下使用是否有理由?我不明白汇编器如何对这两种情况做出更好的假设。
NASM 2.10.09 只是使用R_X86_64_32
对于上述两者。更新:2.11 之后的边缘 nasm 提交 6377180 产生相同的 Gas 输出,正如 Ross 提到的,这似乎是一个错误。
我已经解释了我认为我理解的内容R_X86_64_32S
at: https://stackoverflow.com/a/33289761/895245 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 如何解释 32 位值s
编码成两条指令。在第一条指令中,它是立即操作数,32 位值被零扩展到 RAX。在第二条指令中,32 位值是内存操作数中的位移,因此经过符号扩展以形成 64 位地址。
NASM 不应为第二条指令使用无符号 R_X86_64_32 重定位。这不是哪个更好的问题,这里使用 R_X86_64_32 根本就是不正确的。 NASM 将允许地址s
为 0x00000000'80000000,但 CPU 最终会访问 0xFFFFFFFF'80000000。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)