我有一段简单的汇编代码可以在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
...
有人可以解释为什么会发生这种情况以及我可以做些什么来避免它?
干杯
答案 0 :(得分:2)
由于未对齐而发生了段错误。对于movapd,4字节对齐是不够的,至少需要16个字节.align 16
。
您在objdump中看到0(%rip)
,因为代码尚未重新定位。执行它时,运行时链接程序将使用正确的偏移量替换它。
答案 1 :(得分:1)
在主线gnu binutils上,在i386和x86_64上,.align n
指令告诉汇编器对齐n个字节(但是,在某些体系结构和平台上,它有其他含义。请参阅文档以获取完整的详细信息)
在OS X上,.align n
指令告诉汇编器对齐2 ^ n个字节。这就是您的代码在Mac上运行的原因。
如果您想要一致的跨平台行为,请改用.p2align
指令,这两个平台都支持该指令,并告诉汇编器对齐2 ^ n个字节。