【问题标题】:local vars in gcc assemblygcc 程序集中的本地变量
【发布时间】:2012-04-27 22:44:29
【问题描述】:

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

void readInput() {
    int buf;
}

teste.S 变为:

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

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

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

void readInput() {
    char buf;
}

输出和上面一样。

【问题讨论】:

标签: gcc assembly compiler-construction


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    缓存命中率

    发生了一些事情。

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

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

      • ESP 减 16 如何使其 16 字节对齐?
      • 如果堆栈由二进制启动代码(称为 crt*.o 的文件)对齐,并且堆栈指针的每次更改都是 n(字节)的倍数,堆栈将保持 n 字节对齐。
      猜你喜欢
      • 2013-07-05
      • 1970-01-01
      • 2018-03-22
      • 2014-01-07
      • 2017-04-29
      • 2014-09-24
      • 1970-01-01
      • 1970-01-01
      • 2011-01-30
      相关资源
      最近更新 更多