作为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
答案 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)
简单的方法:找到空函数用一个参数调用另一个函数。如果参数直接存储到堆栈中(没有推送),那么这就是额外空间的用途。