main()序言中堆栈指针对齐的目的是什么

Bus*_*ush 10 c x86 assembly gdb

main使用gcc -g -o program -m32 program.c64位机器(运行ubuntu 14.04)编译的函数(简单玩具程序)的序言中,我得到以下反汇编:

dump of assembler code for function main:
   0x08048e24 <+0>: push   %ebp
   0x08048e25 <+1>: mov    %esp,%ebp
   0x08048e27 <+3>: and    $0xfffffff0,%esp
   ...
Run Code Online (Sandbox Code Playgroud)

<+3>指令的目的是什么?也就是说,为什么要$esp指向一个16对齐的地址?

oua*_*uah 9

System V AMD64 ABI(x86-64 ABI)需要16字节堆栈对齐.double需要8字节对齐,SSE扩展需要16字节对齐.

gcc 文档将其指向其文档中的-mpreferred-stack-boundary选项:

-mpreferred-stack-boundary = num

尝试将堆栈边界保持对齐2到num字节边界.如果未指定-mpreferred-stack-boundary,则默认值为4(16字节或128位).

警告:为禁用SSE扩展的x86-64体系结构生成代码时,可以使用-mpreferred-stack-boundary = 3来保持堆栈边界与8字节边界对齐.由于x86-64 ABI需要16字节堆栈对齐,因此这是ABI不兼容的,并且旨在用于堆栈空间是重要限制的受控环境中.当使用16字节堆栈对齐编译的函数(例如来自标准库的函数)使用未对齐的堆栈调用时,此选项会导致错误的代码.在这种情况下,SSE指令可能导致未对齐的内存访问陷阱.此外,对于16字节对齐的对象(包括x87 long double和__int128),错误地处理变量参数,从而导致错误的结果.您必须使用-mpreferred-stack-boundary = 3构建所有模块,包括任何库.这包括系统库和启动模块.