[英]NASM x86_64 assembly in 32-bit mode: Why does this instruction produce RIP-Relative Addressing code?
[英]Segfault with RIP-relative addressing on Linux
我有一段簡單的匯編代碼,它可以在 Mac OS X (x86-64) 上正常工作,但在 Linux (x86-64) 上卻不能正常工作:
.data
.align 4
foo: .quad 1,2
.text
.globl fun
fun:
movapd foo(%rip), %xmm1
ret
從一個簡單的 C 程序調用:
int main(void){
fun();
return 0;
}
在 Mac 上發生的情況是 xmm1 寄存器填充了位置 foo 的數據,即 GDB 中的數據:
(gdb) p $xmm1
$2 = {
...
v2_int64 = {2, 1},
uint128 = 0x00000000000000020000000000000001
}
當我在 Linux 下運行相同的代碼時,它會出現段錯誤 - 似乎 foo 標簽對應於 0x0:
> objdump -d asm.o
...
Disassembly of section .text:
0000000000000000 <fun>:
0: 66 0f 28 0d 00 00 00 movapd 0x0(%rip),%xmm1
...
有人可以解釋為什么會發生這種情況以及我可以做些什么來避免它?
干杯
段錯誤是由於未對齊而發生的。 4 字節對齊對於 movapd 來說是不夠的,您至少需要 16 字節.align 16
。
您會在 objdump 中看到0(%rip)
,因為代碼尚未重新定位。 當您執行它時,運行時鏈接器將用正確的偏移量替換它。
在主線 gnu binutils 上,在 i386 和 x86_64 上, .align n
指令告訴匯編器對齊到 n 個字節(但是,在某些體系結構和平台上,它具有其他含義。有關完整詳細信息,請參閱文檔)。
在 OS X 上, .align n
指令告訴匯編器對齊到 2^n 字節。 這就是您的代碼在 Mac 上運行的原因。
如果您想要一致的跨平台行為,請改用.p2align
指令,該指令在兩個平台上都受支持,並告訴匯編器對齊到 2^n 字節。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.