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

时间:2015-11-23 10:18:03

标签: c assembly x86 gdb

main函数(一个简单的玩具程序)的序言中,使用gcc -g -o program -m32 program.c在64位计算机上运行(运行ubuntu 14.04),我得到以下反汇编:

dump of assembler code for function main:
   0x08048e24 <+0>: push   %ebp
   0x08048e25 <+1>: mov    %esp,%ebp
   0x08048e27 <+3>: and    $0xfffffff0,%esp
   ...

&lt; + 3&gt;指令的目的是什么? 也就是说,为什么$esp指向一个16对齐的地址?

1 个答案:

答案 0 :(得分:0)

i386 System V ABI的现代版本与x86-64 System V(@ouah的答案提到)具有相同的16字节堆栈对齐要求/保证。

这包括保证内核%esp处将_start对齐16。因此,也保持16字节对齐的CRT启动代码将调用main,堆栈对齐16字节。

从历史上看,i386 System V ABI只需要4字节的堆栈对齐,而将堆栈对齐16位只是编译器可以选择进行的工作;当GCC只是一个好主意,而不是法律(在MacOS和Linux上)时,默认设置为-mpreferred-stack-boundary=4

我认为某些BSD版本仍然不需要32位代码中的16字节堆栈对齐,因此想要对doubleint64_t或特别是XMM向量,确实需要手动对齐堆栈,而不是依赖传入的堆栈对齐。


但是,即使在现代Linux上,-m32的GCC的32位模式(main)行为也不假定main的调用者(或内核)遵循ABI ,然后手动对齐堆栈。

有关更多信息,请参见Responsibility of stack alignment in 32-bit x86 assembly;另一个问题是,过时的指令会基于需要的假设而导致混乱。

在x86-64上的

GCC不会 这样做,只是利用了x86-x中始终要求16字节堆栈对齐 的事实64系统V ABI。 (以及Windows x64 ABI)。