提问者:小点点

x86-64Linux堆栈错位没有seg故障


我只是通过Nick Desaulniers工作:让我们写一些X86-64文件h4. s:

.text
.globl main
 main:
#  subq $8, %rsp
movq $0, %rdi
call _exit

他在Mac上运行,说运行上面的会导致分段错误。我在opensuse 13.1上运行,只是打电话

gcc h4.s

编译和链接。当堆栈指针被调整或该行被注释掉时,我不会收到seg错误。有人知道为什么不吗?SP不需要对齐到16字节的边界吗?


共1个答案

匿名用户

x86-64 System VABI要求栈指针在进入例程时为8 mod 16字节(16B在调用之前对齐,在堆栈上推送返回地址之后为16 8)。

但是,如果堆栈不对齐,并且有人在某个时候想要做一些基于他们有一个16B对齐堆栈的假设的事情。例如,发出一个对齐的xmm指令,如“movdqa[rsp],…”,那么你可以得到一个实际的seg错误。或者假设一些其他类型的堆栈对齐假设的其他错误。

总而言之:在调用之前简单地对齐堆栈通常不会出错。

就像C未定义的行为一样,如果你违反规则,它不需要失败,但它可能会失败。现在发生的工作可能会在未来或其他系统上中断。

允许编译器在任何地方使用SSE一次向/从局部变量复制16个字节,因为ABI保证,并且x86-64至少保证SSE2。

例如,当从一个不对齐RSP的函数调用glibc scanf分割时会出现错误——现代的glibc构建包括一个movaps,用于一次将16个字节复制到本地结构或数组。旧版本的glibc不需要堆栈对齐(当您正确设置AL=0时)。