我是汇编语言的新手,我想知道本地变量,为什么我们(或编译器)通常通过减少" ESP"寄存器(或在过程的序幕上,随着过程结束,我们将" 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
通常,您只能使用堆栈指针上方的堆栈。堆栈指针定义了堆栈的末端。在堆栈指针下访问可能会或可能行不通。如果您调用另一个功能,它尤其将无法工作,因为返回地址将被推开,并且所谓的功能将开始使用堆栈指针中的堆栈,从而覆盖当地人。即使在叶子功能中,异步的东西(例如信号处理程序)也可以使用堆栈,并且他们还假设堆栈指针下的所有内容都未使用。
此外,操作系统可能正在按需增长堆栈,并且还使用了堆栈指针。如果您在堆栈指针下访问,则可能不会映射内存,如果操作系统抓住您的程序将崩溃。
请注意,一些呼叫约定(例如X86-64 ABI)允许在堆栈指针下进行所谓的红色区域。该区域保证未修饰,并且可以在不调整堆栈指针的情况下用于当地人的叶子功能。
MR之后。@Jester有用的答案,我看上去"红色区域",我发现它对我很有帮助,所以我与您分享首先,这是根据本文的AMD64 ABI的定义http://eli.thegreenplace.net/2011/09/06/stack-frame-layout-on-x86-64/
"超出位置的128个字节区域被认为是保留的,不得通过信号或中断处理程序进行修改。因此,功能可以使用此区域用于跨函数调用中不需要的临时数据。
这是一个与我非常相似的问题:
https://softwareengineering.stackexchange.com/questions/230089/what-is-the-purpose-of-red-zone/230095#230095