2011-10-17 74 views
1

我正在编写一个汇总堆栈的报告。如果你点击我的个人资料,你会看到我已经做了一段时间。现在,我有一些麻烦,因为在GDB上它向我展示了与视觉工作室不同的东西。因此,我不太了解我对基本指针和堆栈指针的理解,并且我希望如果我错了,有人能够带领我走向正确的方向。有关基址指针和堆栈指针的问题

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

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

  1. 一般来说,在每个函数调用的入口,一组在当前ESP位置创建的,这就是我们所谓的“堆栈的顶部”。它是否正确?

  2. 当旧的ebp被推入堆栈时,它是否被推到了esp第一次指向的地方?

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

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

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

我知道有很多问题。但是谢谢你的时间!


谢谢你的回应,先生!

@iSciurus

我很困惑大家如何界定尤指这是压入堆栈中的最新条目指向。

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

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

所以esp减少了16个字节。所以这是大小的这个函数调用的堆栈。局部变量紧接在返回地址后面(ebp-4,ebp-8等)。那么esp的总体目标是什么?据我所知,当我们试图访问比这个更小的地址时,会发生堆栈溢出。

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

这是图片我心目中(向下增长)

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

对不起,这些长期问题。但我真的很感谢你的帮助。

回答

1
  1. 为了正确,在当前esp位置创建堆栈帧,而不是堆栈本身。该堆栈在线程启动时创建一次,每个线程都有自己的堆栈,这只是进程内存空间中的一个区域。堆栈帧是每个函数入口实际创建的,它是线程堆栈内的一个区域。

  2. 不,它被压入地址[old_esp - 4](或[old_rsp - 8]在x64)的,因为尤其是在堆栈和点到最低使用的地址的顶部。堆栈中的下一个DWORD(或QWORD)是空闲的,并且ebp被推送到那里。

  3. 没错,这就是通常与子ESP,值完成

  4. 号第一,ESP是向下移动在堆栈在最低使用的地址指向,而不是在下一个可用空间。其次,请记住,esp可以指向任何地方,不仅可以指向堆栈:直到使用堆栈相关的指令(如push/pop)才可以。

  5. 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指向“上面”的所有数据的价值,看起来更像是“顶”。虽然它仍然是使用最少的地址。

+0

谢谢,先生。我仍然有一点疑问,我编辑了我的帖子。如果你有时间,你介意看看?谢谢。 – CppLearner

+0

非常感谢。我想知道的最后一件事是,在局部变量下面,有一个传统上称为“动态内存”的区域,它尚未被任何进程占用(希望)。所以这就是我们在同一个过程中称之为“随意增加堆栈”的地方。说你正在调用“新”运营商的过程中。新的存储现在在ESP下创建。 ESP现在向下移动吗?谢谢。 – CppLearner

+0

不,esp不会改变,因为esp与堆没有任何共同之处。 – asd