为什么没有变量时main初始化栈帧 [英] Why does main initialize stack frame when there are no variables
问题描述
为什么要这段代码:
#include "stdio.h"
int main(void) {
puts("Hello, World!");
}
决定初始化堆栈帧吗?这是汇编代码:
decide to initialize a stack frame? Here is the assembly code:
.LC0:
.string "Hello, World!"
main:
push rbp
mov rbp, rsp
mov edi, OFFSET FLAT:.LC0
call puts
mov eax, 0
pop rbp
ret
为什么编译器仅初始化堆栈帧以使其销毁以后,撤消它曾经被使用过吗?这肯定不会在主函数的外部引起任何错误,因为我从不使用堆栈,因此不会引起任何错误。为什么用这种方式编译?
Why does the compiler initialize a stack frame only for it to be destroyed later, withoput it ever being used? This surely wont cause any errors on the outside of the main function because I never use the stack, so I wont cause any errors. Why is it compiled this way?
推荐答案
每个编译函数中都有这些步骤是未优化的编译器基准。它在拆卸时看起来很干净,很有意义。但是,编译器可以优化输出以减少没有实际效果的代码的开销。您可以通过使用不同的优化级别进行编译来查看。
Having these steps in every compiled function is the "baseline" for the compiler, unoptimized. It looks clean in disassembly, and makes sense. However, the compiler can optimize the output to reduce overhead from code that has no real effect. You can see this by compiling with different optimization levels.
所获得的就像此:
.LC0:
.string "Hello, World!"
main:
push rbp
mov rbp, rsp
mov edi, OFFSET FLAT:.LC0
call puts
mov eax, 0
pop rbp
ret
这是在GCC中编译的,没有优化。
That's compiled in GCC with no optimization.
添加标志-O4给出此输出:
Adding the flag -O4 gives this output:
.LC0:
.string "Hello, World!"
main:
sub rsp, 8
mov edi, OFFSET FLAT:.LC0
call puts
xor eax, eax
add rsp, 8
ret
您会注意到,这仍然会移动堆栈指针,但是跳过更改基址指针,并避免与此相关的耗时的内存访问。
You'll notice that this still moves the stack pointer, but it skips changing the base pointer, and avoid the time-consuming memory access associated with that.
假定堆栈在16字节边界上对齐。在返回地址被压入的情况下,这将剩下另外8个字节要减去,以到达函数调用之前的边界。
The stack is assumed to be aligned on a 16-byte boundary. With the return address having been pushed, this leaves another 8 bytes to be subtracted to get to the boundary before the function call.
这篇关于为什么没有变量时main初始化栈帧的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!