【问题标题】:memory stack: sub 20 from esp内存堆栈:来自 esp 的 sub 20
【发布时间】:2021-05-11 11:58:06
【问题描述】:

我无法在这个 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

如果这个可视化是正确的,那么当你甚至没有任何关于可以放置下一个局部变量的位置的引用时,你怎么能将任何东西压入堆栈呢?

【问题讨论】:

    标签: assembly memory x86 stack instructions


    【解决方案1】:

    “低地址”是堆栈指针ESP 所在的位置。将任何内容推送到堆栈都会将其存储在此地址之下。

    存储局部变量将使用带有负偏移量的EBP 相对寻址模式

    在您的示例中,EBPESP 之间有 20 个字节的差异。
    在没有任何推送的情况下,MOVing 到 ESPpoints 填充该 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
    

    EAXEDX彼此相等。

    【讨论】:

    • Moving 到 ESPpoints 填充该 20 字节区域的最低 4 个字节。相反,第一个push 将存储在该 20 字节区域下方。
    • 不,PUSH 减少堆栈指针!第一个推送的 dword 将位于 [ebp-24] 。请参阅编辑后的答案。
    • 留出 20 字节区域(在本例中)用于存储局部变量。您的程序将通过易于记忆的名称来引用其中的项目。汇编器知道偏移量(小的负数)。推送仍然是可能的,但“组织性”稍差,而且PUSH 指令比单纯的MOV 慢。
    • 当然,这就是编译器最擅长的,以符号形式组织我们提交的内容。如果您的代码使用 7 个局部变量 (dword),那么编译器将编码 sub esp, 28。 (7 * 4)
    • 是的,这是有道理的。这非常有用。感谢您的宝贵时间。
    猜你喜欢
    • 2014-06-24
    • 2011-08-15
    • 2017-02-08
    • 2012-06-03
    • 1970-01-01
    • 2012-12-20
    • 2018-03-29
    • 2011-10-21
    • 2011-06-13
    相关资源
    最近更新 更多