问题描述
我无法在这个 stackoverflow 线程中找到答案。 https://stackoverflow.com/a/1395646
答案中间写着Most function prologs look something like:...
据我了解上述答案中的指令-->第一条指令将 ebp 压入堆栈。然后我们将 esp 移到 ebp 中。最后我们从 esp 中减去 20,使 esp 点从原来的位置往下减 20 个地址。
根据上面的说明,我将堆栈想象成这样。
high address
__________________________
| (an address) | <-- ebp
..........................
..........................
| | <-- esp points to an address 20
| | bytes lower
| |
| |
| |
|________________________|
low address
如果这个可视化是正确的,那么当你甚至没有任何关于可以放置下一个局部变量的位置的引用时,你怎么能把任何东西压入堆栈?
解决方法
“低地址”是堆栈指针 ESP
所在的位置。将任何内容推入堆栈将其存储在此地址下。
存储局部变量将使用带有负偏移量的 EBP
相对寻址模式。
在您的示例中,EBP
和 ESP
之间有 20 个字节的差异。
在没有任何推送的情况下,MOV
指向 ESP
指向的位置会填充该 20 字节区域的最低 4 个字节。相反,第一个 PUSH
将存储在 20 字节区域之下。只有 PUSH
指令会预先降低堆栈指针。 MOV
按原样使用 ESP
。
以下存储到内存中的相同地址:
mov [ebp-20],eax
mov [esp],eax
现在,如果我们向堆栈中push
一些新数据,那么 ESP
会改变但 EBP
仍然存在,因此以下情况为真:
push ebx <<< The first push
mov eax,[ebp-20] <<< Still at -20
mov edx,[esp+4] <<< Now at +4
EAX
和 EDX
彼此相等。