为什么要为局部变量保留堆栈 space?

why preserve stack space for local variables?

我是汇编语言的新手,我想知道局部变量,为什么我们(或编译器)通常通过递减 "ESP" 寄存器在堆栈上为它们保留 space在程序的序言和程序结束时,我们再次分配 "ESP" 它的旧值。喜欢这个代码示例:

; a procedure that create the stack frame then assign 10, 20 values for two local variables then return to caller

two_localv_proc PROC
push ebp
mov ebp,esp
sub esp,8
mov DWORD PTR [ebp-4],10
mov DWORD PTR [ebp-8],20
mov esp,ebp
pop ebp
ret
two_localv_proc ENDP

如果我们删除 (sub esp,8) 行和 (mov esp,ebp) 行,最后一个代码片段将完全如此

 two_localv_proc PROC
push ebp
mov ebp,esp
mov DWORD PTR [ebp-4],10
mov DWORD PTR [ebp-8],20
pop ebp
ret
two_localv_proc ENDP

所以我们(或编译器)为什么要这样做! ,只要 "ESP" 指针不会受到在堆栈上存储值的影响,我们为什么不使用堆栈内存来存储我们的局部变量,代码如下:

mov DWORD PTR [ebp-8],20

一般情况下只能使用栈指针以上的栈。堆栈指针定义堆栈的结尾。在堆栈指针下访问可能有效也可能无效。如果您调用另一个函数,它尤其不会工作,因为 return 地址将被压入,并且被调用函数将开始使用堆栈指针中的堆栈,从而覆盖您的局部变量。即使在叶函数中,诸如信号处理程序之类的异步事物也可能会使用堆栈,并且它们还假定堆栈指针下的所有内容都未被使用。

此外,OS 可能会按需增加您的堆栈,它也为此使用堆栈指针。如果您在堆栈指针下访问,内存甚至可能不会被映射,如果 OS 发现您这样做,您的程序将崩溃。

请注意,某些调用约定(例如 x86-64 abi)允许在堆栈指针下使用所谓的红色区域。该区域保证不被修改,可以在不调整堆栈指针的情况下用于本地的叶函数。

在先生之后@Jester 有用的答案我查看了 "red zone",发现它对我很有帮助,所以我与你分享 首先,根据本文,这是 AMD64 ABI 的定义 http://eli.thegreenplace.net/2011/09/06/stack-frame-layout-on-x86-64/

"The 128-byte area beyond the location pointed to by %rsp is considered to be reserved and shall not be modified by signal or interrupt handlers. Therefore, functions may use this area for temporary data that is not needed across function calls. In particular, leaf functions may use this area for their entire stack frame, rather than adjusting the stack pointer in the prologue and epilogue. This area is known as the red zone."

这是一个与我非常相似的问题:

https://softwareengineering.stackexchange.com/questions/230089/what-is-the-purpose-of-red-zone/230095#230095