3

当我编译下面的函数时: gcc -S teste.c

void readInput() {
    int buf;
}

teste.S 变为:

readInput:
     pushl   %ebp
     movl    %esp, %ebp
     subl    $16, %esp
     leave
     ret

我的疑问是:为什么从 16 个字节中减去 %esp,对于 int 不应该是 4 个字节吗?跟对齐有关系吗?

当我编译这个时会发生类似的事情:

void readInput() {
    char buf;
}

并且输出与上面相同。

4

3 回答 3

0

对于 SSE2,堆栈可能保持 16 字节对齐。(有 128 位=16*8)寄存器。对于 64 位,这甚至是强制性的。

严格来说,对于使用叶子程序的非 SSE,这个要求可以省略。

于 2012-04-17T09:52:24.703 回答
0

缓存命中率

有几件事正在发生。

  1. 未经优化的编译将留下代码生成器设计的工件。
  2. 如果没有进一步的调用或 -g,则几乎不需要完整的堆栈帧。
  3. 分配空间时,如果函数不是叶节点,则在高速缓存行边界或 1 的 1/2 n子单元上分配可能是有意义的。这个想法是,未来的调用可能处于循环中,如果新的堆栈帧与两个缓存行重叠,或者n + 1 个缓存行,那么它们将浪费空间并降低命中率。一段时间以来,缓存命中率一直是至关重要的。由于同样的原因,您有时会看到模块和更大的数据结构过度对齐。当然,这与保持堆栈使用量小以提高缓存效率的合理目标相冲突。
于 2012-04-16T16:45:05.827 回答
0

基本问题是您没有使用优化,因此它不会努力最小化它分配的空间或它生成的代码。所以这里发生的是,为可能需要的东西分配了一堆堆栈空间(展开处理程序,调用 setjmp/longjmp/alloca 或其他编译器内置函数),但在你的情况下不需要永远不要调用函数或使用可能需要它们的特性。

如果你使用优化(甚至只是-O1),这个空间将会消失,因为优化器会看到它未使用。

于 2012-04-16T16:25:21.963 回答