如何定义windows x86堆栈中的堆栈?

时间:2013-02-14 17:24:16

标签: windows memory-management assembly operating-system stack

首先,我将展示对堆栈的不了解,然后我会问一个无法很好回答的温和连贯的问题,因为这个问题不够具体,无法引出一个好的组合答案。

因此,当程序运行时,函数被推送到堆栈 - 这意味着堆栈指针递增或递减?

堆栈内存分配中究竟存储了什么?指向可变数据的指针,指向程序的est?我只是不明白究竟是什么存储在堆栈上(什么数据类型,什么类型的引用,它们如何存储)我希望函数存储其局部变量指针和指向调用它的地址的指针,以便它可以返回

此外,windows x86虚拟内存分配实际上将单个虚拟内存块映射到任意多个物理内存地址,因此堆栈在Windows x86系统的物理内存中是连续的还是不连续的?

最后,假设堆栈存储在x86上32位窗口上的应用程序的用户分配虚拟内存中,堆栈指针(引用高或低内存地址?)是31位(31因为用户分配和高2GB保留给内核分配)little-endian引用,对吧?

当数据到达堆栈时(如输入函数并为新DWORD分配内存),存储在该DWORD中的数据将被推送到堆栈并且堆栈指针会递增还是递减?系统如何同时识别堆栈的两端?

---- ESP在这?

| - 变量x的引用地址

| - 整数数据存储在函数1中变量x的存储器地址中

| ----功能1块以上^^

|

|

----或ESP在这?

从这里,参考地址和整数数据将弹出到寄存器中,mov操作将整数数据存储在分配的内存位置?

当新数据到达堆栈时,我听说堆栈“向下”增长但这似乎是不合理的,因为只有更高和更低的内存地址 - 我知道只有堆栈的一端需要递增/递减,但它是高地址还是低地址,堆栈长度(高度)是如何划分的?当堆栈“增长”得太大时,系统如何理解?

对不起所有的问题,但我一直在做很多阅读,用于描述我一直在阅读的概念的术语在我的词汇表中没有很好地实现。我还检查了谷歌,维基百科和这个网站,并找不到解决我的具体问题的解释。

感谢。

2 个答案:

答案 0 :(得分:3)

确定。堆栈只是一种抽象数据类型。好。一组内存,您可以将(puhs)数据放在最后并将其删除(弹出)。从正面或背面向上或向下增长,或根据其实施方式而增长。好。

现在(a)系统堆栈有点定义了。它是由程序或本地线程存储或其他任何东西分配的RAM区域。指针位于其内存位置的“末端”,并向后朝顶部增长。推送将数据放在堆栈的当前位置(减去数据大小,使其不会越过末尾),因此在写入之前递减。强制执行时,新的堆栈指​​针指向最后一个“推”值的开始。

为什么倒退?公约和易用性。考虑一个嵌入式系统或一些RAM资源更有限的旧系统。如果我们将堆启动到RAM的顶部 - 就在代码和静态/ const数据之后,我们需要在同一个RAM空间中存储另一种类型的存储,为什么不从后面增长呢?这样您就不必担心每个部分的大小。当所有RAM都被使用时,它们将在中间的某个地方相遇(并且下一次写入将通过堆栈溢出进行繁荣。)易于维护和创建并且高效 - 无需猜测正确的大小等。

刚开始。虚拟地址等在这一点上不应该太担心你。如果你的空间不足,他们只是帮助“走动”部分。我怀疑堆栈是否分布在多个页面上,但如果是,请让操作系统处理它并且一切都很好(而且速度很慢,但这是另一个故事。)

现在堆栈上发生了什么 - 无论你想要什么。通常,参数传递给的函数超出了可以放入寄存器的范围,在函数之外不需要的范围变量,有时用于此指针的c ++粘合剂,有时在使用alloca()来处理堆栈之类的动态内存时更多 - 你会经常在线程代码中看到这个,以帮助防止内存写入竞争条件等。此外,由值返回的值不适合寄存器也通常在堆栈上返回。基本上,当函数寄存器填满并且需要更多空间时,您在函数中看到的每个局部变量都很有可能在堆栈中生存。因此,许多系统都试图确保堆栈内存尽可能快。

要回答您剩下的问题 - 系统可能会或可能不会知道堆栈的两侧 - 取决于平台。我猜测窗口是否通过跟踪知道堆栈启动是否写入地址超出了结束。不成对的推/弹会破坏程序的一天,有时也会导致操作系统挂起(现在不那么天)。由于我没有直接的经验,我无法回答你的Windows特定的32/31位地址问题。其他人可以抓住那一部分。最后,堆栈增长方向令人困惑的术语。我通常认为系统堆栈正在“向上”增长,但这可能只是我。

希望这有助于为您解决一些问题!

答案 1 :(得分:1)

  

当程序运行时,函数被推送到堆栈 - 这意味着堆栈指针递增或递减?

这取决于堆栈的实现方式。如果它从内存末尾向后增长,则递减。如果它从内存开始向前增长,则会递增。

  

堆栈内存分配中究竟存储了什么?

无论给定的程序或编程语言是什么推入堆栈。这可以包括返回地址,值类型,指向对象的指针和堆栈帧。

  

windows x86虚拟内存分配实际上将单个虚拟内存块映射到任意多个物理内存地址,因此堆栈在Windows x86系统的物理内存中是连续的还是不连续的?

见这里:http://www.dirac.org/linux/gdb/02a-Memory_Layout_And_The_Stack.php

  

当堆栈“增长”得太大时,系统如何理解?

它击中了堆的顶部。