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

时间:2021-11-05 19:13:49

as a beginner of asm, I am checking gcc -S generated asm code to learn.

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

why gcc 4.x default reserve 8 bytes for stack when calling a method?

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

func18 is the empty function with no return no param no local var defined. I can't figure out why 8 bytes is reserved here (neither any forum/site mention for the reason, ppl seems take it for granted) is it for the %ebp just push? or return type?! many thx!

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

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

3 个解决方案

#1


8  

Some instructions require certain data types to be aligned to as much as a 16-byte boundary (in particular, the SSE data type __m128). To meet this requirement, gcc ensures that the stack is initially 16-byte aligned, and allocates stack space in multiples of 16 bytes. If only a 4-byte return address and 4-byte frame pointer need to be pushed, 8 additional bytes are needed to keep the stack aligned to a 16-byte boundary. However, if gcc determines that the additional alignment is unnecessary (i.e. the fancy data types are not used and no external functions are called), then it may omit any additional instructions used to align the stack. The analysis necessary to determine this may require certain optimization passes to be performed.

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

See also the gcc documentation for the option -mpreferred-stack-boundary=num.

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

#2


0  

As richard mentioned above, it's all because of optimization, showing below. but still I got no idea why 8 bytes reserved is something optimized?!

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

original c

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

compile without optimization flag specified

编译时没有指定优化标志

    .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

with -Os optimization flag, no more stack reserve

使用-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

#3


0  

Easy way to find out: Have you empty function call another function with one parameter. If the parameter is stored directly to the stack (no push), then that's what the extra space is for.

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

#1


8  

Some instructions require certain data types to be aligned to as much as a 16-byte boundary (in particular, the SSE data type __m128). To meet this requirement, gcc ensures that the stack is initially 16-byte aligned, and allocates stack space in multiples of 16 bytes. If only a 4-byte return address and 4-byte frame pointer need to be pushed, 8 additional bytes are needed to keep the stack aligned to a 16-byte boundary. However, if gcc determines that the additional alignment is unnecessary (i.e. the fancy data types are not used and no external functions are called), then it may omit any additional instructions used to align the stack. The analysis necessary to determine this may require certain optimization passes to be performed.

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

See also the gcc documentation for the option -mpreferred-stack-boundary=num.

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

#2


0  

As richard mentioned above, it's all because of optimization, showing below. but still I got no idea why 8 bytes reserved is something optimized?!

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

original c

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

compile without optimization flag specified

编译时没有指定优化标志

    .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

with -Os optimization flag, no more stack reserve

使用-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

#3


0  

Easy way to find out: Have you empty function call another function with one parameter. If the parameter is stored directly to the stack (no push), then that's what the extra space is for.

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