【问题标题】:Questions regarding base pointer and stack pointer关于基指针和栈指针的问题
【发布时间】:2011-12-09 01:58:01
【问题描述】:

我正在写一份报告来总结堆栈。如果您单击我的个人资料,您会看到我已经这样做了一段时间。现在,我遇到了一些麻烦,因为在 GDB 上它向我展示了与在 Visual Studio 上不同的东西。

因此,我不太确定自己对基指针和堆栈指针的理解,如果我错了,我希望有人能引导我走向正确的方向。

对于 x86 计算机,堆栈通常是向下增长的(从较高的内存地址到较低的内存地址)。

所以当一个程序开始时,我们调用了 main 函数。

  1. 一般来说,在每次函数调用的入口处,都会在当前esp位置创建一个栈,也就是我们所说的“栈顶”。这是正确的吗?

  2. 当旧的 ebp 被压入堆栈时,它是否被压入了 esp 最初指向的位置?

  3. 之后,esp 会向下移动,指向一个空的内存位置,对吗?

  4. 最后,esp 总是在变化,向下移动指向下一个可用内存空间。对吗?

  5. esp 是每字节向下移动,还是每 4 字节向下移动?

我知道有很多问题。但是感谢您的宝贵时间!


谢谢您的回复,先生!

@iSciurus

我很困惑每个人如何定义 esp 指向最近被压入堆栈的条目。

对于 x86,由于堆栈向下增长,根据您的解释,esp 将首先指向堆栈的最低地址。当我查看汇编代码时,我们有

   0x080483f4 <+0>: push   %ebp
   0x080483f5 <+1>: mov    %esp,%ebp
   0x080483f7 <+3>: sub    $0x10,%esp

所以 esp 减少了 16 个字节。所以这是这个函数调用的堆栈的size。局部变量紧跟在返回地址之后(ebp-4、ebp-8 等)。那么这里 esp 的总体目的是什么?据我了解,当我们尝试访问小于该地址的地址时,会发生堆栈溢出。

最后一件事是:当我们说栈顶时,我们指的是最低地址吗(对于 x86)。

这是我心目中的画面(向下生长)

[Parameter n          ]
...
[Parameter 2          ]
[Parameter 1          ]
[Return Address       ]   0x002CF744
[Previous EBP         ]   0x002CF740  (current ebp)
[Local Variables      ]   
-- ESP

很抱歉这些冗长的问题。但我真的很感谢你的帮助。

【问题讨论】:

    标签: memory-management pointers stack base


    【解决方案1】:
    1. 正确地说,堆栈帧是在当前 esp 位置创建的,而不是堆栈本身。堆栈在线程启动时创建一次,每个线程都有自己的堆栈,堆栈只是进程内存空间中的一个区域。栈帧是每个函数入口处实际创建的,它是线程栈内的一个区域。

    2. 不,它被推送到地址 [old_esp - 4](或 x64 中的 [old_rsp - 8]),因为 esp 是堆栈并指向最低使用的地址。堆栈中的下一个 DWORD(或 QWORD)是空闲的,并且 ebp 被推送到那里。

    3. 是的,这通常通过 sub esp, value

    4. 完成
    5. 没有。首先, esp 向下移动,指向堆栈中使用的最低地址,而不是下一个可用空间。其次,请记住,esp 可能指向任何地方,而不仅仅是堆栈:在您使用与堆栈相关的指令(如 push/pop)之前,它是可以的。

    6. Esp 按机器字大小移动:在 x86 中它每 4 个字节移动,而在 x64 中它每 8 个字节移动。


    esp 的总体目的几乎总是相同的:存储栈顶。所有与堆栈相关的指令(如 pop/push)都使用 esp 作为参数。在 x86 中,ebp 和 esp 都用于存储有关堆栈帧的信息(对应的底部和顶部)。也许,您对这种冗余感到困惑。但是,在 x64 中,只有 rsp 用于基于堆栈的参数,而 rbp 是一个通用寄存器。

    堆栈中的缓冲区溢出怎么办,当代码尝试写入高于数组(或结构或其他)的最后一个元素时,它们通常会发生。堆栈向下增长,但数组向上增长。当我们写得更高时,我们可以访问返回地址、SEH 处理程序以及调用者的内部变量。

    是的,当我们说顶部时,我们指的是最低地址。因此,大多数调试器以相反的顺序显示堆栈:

    -- ESP
    [Local Variables      ]
    [Previous EBP         ]   0x002CF740  (current ebp)
    [Return Address       ]   0x002CF744
    [Parameter 1          ]
    [Parameter 2          ]
    ...
    [Parameter n          ]
    

    这里,ESP 指向所有数据“上方”的值,看起来更像“顶部”。虽然它仍然是最低使用的地址。

    【讨论】:

    • 谢谢您,先生。我仍然有一点疑问,我编辑了我的帖子。如果你有时间,你介意看看吗?谢谢。
    • 非常感谢。我想知道的最后一件事是,在局部变量下面,有一个传统上称为“动态内存”的区域,它还没有被任何进程占用(希望如此)。所以这就是我们为同一个进程称为“随心所欲地增长堆栈”的地方。在您称为“新”运算符的过程中说。新存储现在在 ESP 下创建。 ESP现在向下移动吗?谢谢。
    • 不,esp 没有改变,因为 esp 与堆没有任何共同之处。
    猜你喜欢
    • 2012-05-03
    • 1970-01-01
    • 2014-05-13
    • 2015-05-19
    • 2021-09-17
    • 1970-01-01
    • 1970-01-01
    • 2016-10-04
    • 1970-01-01
    相关资源
    最近更新 更多