初学者对x86堆栈的困惑

首先,我想知道这个模型是否是堆栈“框架”过程的准确表示.

我被告知在概念上,堆栈就像一个可乐瓶.糖在底部,你把它填满了顶部.考虑到这一点,如果EIP在另一个瓶子中(它在代码段中,而不是堆栈段),Call如何告诉EIP寄存器“定位”被调用的函数?我在YouTube上观看了一段视频,称“RAM的代码段”(保存功能的地方)是EIP寄存器所在的位置.

最佳答案
通常,计算机程序使用四种存储区域(也称为区段或段):

>文本部分:包含程序代码.当程序由操作系统加载时保留.此区域是固定的,在程序运行时不会更改.这最好被称为“代码”部分,但名称有历史原因.
>数据部分:包含程序的变量.程序加载并初始化为程序员定义的值时保留.程序在执行时可以更改这些值.
>堆栈:这是一个动态的内存区域.它用于存储函数调用的数据.它基本上通过将值“推”到堆栈并从堆栈弹出来工作.这也称为“LIFO”:先进先出.这是函数的局部变量所在的位置.如果函数完成,则数据将从堆栈中删除并丢失(基本上).
>堆:这也是一个动态内存区域.编程语言中有特殊功能,可根据程序的要求“分配”(保留)该区域的一部分.如果不再需要,可以使用另一个函数将此区域返回到堆中.当数据被明确释放时,它可以用于存储比仅仅函数调用(不同于堆栈)更长寿的数据.

文本和数据部分的数据存储在程序文件中(它们可以在Linux中找到,例如使用objdump(在名称中添加一个).堆栈和堆不会存储在文件中的任何位置,因为它们是动态分配的(在-demand)由程序本身.

通常,在加载程序之后,将内存区域重新定义视为单个大块,其中堆栈和堆都位于其中.它们从该区域的另一端开始并朝向彼此生长.对于大多数体系结构,堆从低到高的内存地址(升序)和堆栈向下(降序)增长.如果它们相交,程序就会耗尽内存.由于这可能未检测到,堆栈可能会损坏(更改外部数据)堆,反之亦然.这可能会导致任何类型的错误,具体取决于数据/数据的变化.如果堆栈被破坏,这可能导致程序疯狂(这实际上是木马可能工作的一种方式).然而,现代操作系统应该采取措施在这种情况变得严重之前对其进行检测.

这不仅适用于x86,也适用于大多数其他CPU系列和操作系统,特别是:ARM,x86,MIPS,MSP430(微控制器),AVR(微控制器),Linux,Windows,OS-X,iOS,Android(使用DOS OS),DOS.对于微控制器,通常没有堆(在运行时分配所有内存),堆栈的组织方式可能有所不同;对于基于ARM的Cortex-M微控制器也是如此.但无论如何,这是一个非常特殊的主题.

免责声明:这是非常简化的,所以请不要评论“如何关于bss,const,myspecialarea”;-).对于这些区域,C标准也没有要求,特别是使用堆或堆栈.实际上,有些实现都没有使用.这些是大多数时候嵌入式系统具有小型(8或16位)MCU或DSP.现代架构也使用CPU寄存器而不是堆栈来传递参数并保留局部变量.这些是在目标平台的应用程序二进制接口中定义的.

对于堆栈,您可能会阅读wikipedia article.请注意在典型(微)处理器中实现的数据结构“堆栈”和“硬件堆栈”之间的实现差异.

转载注明原文:初学者对x86堆栈的困惑 - 代码日志