我只是通过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字节的边界吗?
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时)。