我是汇编语言的新手,我想知道局部变量,为什么我们(或编译器)通常通过递减" 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
答案 0 :(得分:1)
通常,您只能使用堆栈指针上方的堆栈。堆栈指针定义堆栈的末尾。在堆栈指针下访问可能会也可能不起作用。如果你调用另一个函数,它尤其不会工作,因为返回地址会被推送,并且被调用的函数也会从堆栈指针开始使用堆栈,从而覆盖你的本地。即使在叶函数中,信号处理程序等异步事件也可能使用堆栈,并且它们也假设堆栈指针下的所有内容都未使用。
此外,操作系统可能会按需增加堆栈,并且还使用堆栈指针。如果你在堆栈指针下访问,内存甚至可能都没有映射,如果操作系统抓到你那么你的程序就会崩溃。
请注意,某些调用约定(例如x86-64 abi)允许在堆栈指针下使用所谓的红色区域。该区域保证不被修改,可以在本地人的叶子函数中使用,而无需调整堆栈指针。
答案 1 :(得分:0)
"%rsp指向的位置之外的128字节区域被认为是保留的,不应被信号或中断处理程序修改。因此,函数可以将此区域用于函数调用不需要的临时数据。特别是,叶子函数可以将这个区域用于它们的整个堆栈帧,而不是调整序言和尾声中的堆栈指针。这个区域被称为红色区域。"
这是一个与我非常相似的问题: