为什么gcc 4.x在调用方法时默认为linux上的堆栈保留8个字节?

时间:2010-03-08 03:12:32

标签: linux gcc assembly stack

作为asm的初学者,我正在检查gcc -S生成的asm代码以供学习。

为什么gcc 4.x在调用方法时默认为堆栈保留8个字节?

func18是空函数,没有返回没有参数,没有定义局部变量。 我无法弄清楚为什么这里保留了8个字节(没有任何论坛/网站提及的原因,ppl似乎认为理所当然) 这是为了%ebp只是推?还是返回类型?!很多thx!

      .globl _func18
  _func18:
     pushl   %ebp 
     movl    %esp, %ebp 
     subl    $8, %esp 
     .text 

3 个答案:

答案 0 :(得分:7)

某些指令要求某些数据类型与16字节边界(特别是SSE数据类型__m128)对齐。为了满足这一要求,gcc确保堆栈最初是16字节对齐的,并以16字节的倍数分配堆栈空间。如果只需要按下4字节的返回地址和4字节的帧指针,则需要8个额外的字节来保持堆栈与16字节边界对齐。但是,如果gcc确定不需要额外的对齐(即没有使用花哨的数据类型并且没有调用外部函数),那么它可以省略用于对齐堆栈的任何附加指令。确定这一点所需的分析可能需要执行某些优化过程。

另请参阅选项-mpreferred-stack-boundary=num的gcc文档。

答案 1 :(得分:0)

正如理查德所提到的,这都是因为优化,如下所示。 但我仍然不知道为什么8字节保留是优化的东西?!

原创c

void func18() {}
int main() {return 0;}

编译时未指定优化标志

    .text                                                                                   
.globl _func18
_func18:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $8, %esp
    leave
    ret
.globl _main
_main:                                                                                      
    pushl   %ebp
    movl    %esp, %ebp
    subl    $8, %esp
    movl    $0, %eax
    leave
    ret
    .subsections_via_symbols
带有-Os优化标志的

,不再有堆栈预留

    .text
.globl _func18
_func18:
    pushl   %ebp
    movl    %esp, %ebp
    leave
    ret
.globl _main
_main:
    pushl   %ebp
    xorl    %eax, %eax
    movl    %esp, %ebp
    leave
    ret
    .subsections_via_symbols

答案 2 :(得分:0)

简单的方法:找到空函数用一个参数调用另一个函数。如果参数直接存储到堆栈中(没有推送),那么这就是额外空间的用途。