【问题标题】:What's the purpose of stack pointer alignment in the prologue of main()main() 序言中栈指针对齐的目的是什么
【发布时间】:2016-02-25 09:49:08
【问题描述】:

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

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

处的指令的目的是什么? 也就是$esp为什么要指向一个16位对齐的地址呢?

【问题讨论】:

    标签: c assembly x86 gdb


    【解决方案1】:

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

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

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

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


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

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

    x86-64 上的 GCC 这样做,只是利用了 16 字节堆栈对齐一直在 x86- 64 系统 V ABI。 (以及 Windows x64 ABI)。

    【讨论】:

      【解决方案2】:

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

      gcc documentation 在其文档中指出 -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 构建所有模块,包括任何库。这包括系统库和启动模块。

      【讨论】:

      • 当我使用 -m32 标志编译时它仍然成立?
      • @Bush 我猜他们使用 16 字节和 -m32 也是因为 SSE。
      • 好吧,并不是每个 x86-64 ABI 都这样做,所以如果人们假装只有一个 x86-64 ABI,我总是有点恼火。在这种情况下,在 Ubuntu 的上下文中,很清楚是指哪个 ABI,但情况并非总是如此。
      • @RudyVelthuis 这是一个公平的评论,我编辑了我的答案以澄清我们正在谈论 System V AMD64 ABI
      猜你喜欢
      • 2011-05-18
      • 2021-01-18
      • 1970-01-01
      • 2010-10-14
      • 2013-06-27
      • 2017-02-08
      • 2010-11-26
      • 1970-01-01
      相关资源
      最近更新 更多