ASM堆栈使用情况

时间:2012-01-06 06:13:42

标签: c++ c assembly inline-assembly

据我了解,当你需要实现函数或者只是用完寄存器时,堆栈可用于存储数据。我的问题是通常使用的堆栈是什么内存。我的印象是这取决于预取过程和其他因素。此外,在什么时候堆叠被加载回RAM。

2 个答案:

答案 0 :(得分:1)

每个进程都有线程,每个线程都有一个堆栈。每个进程都有自己的空间,称为进程地址空间。线程在此进程地址空间中分配其堆栈。这个空间是一个虚拟空间,意味着一个进程获得4 GB的进程空间,它可能并不总是在RAM上。当其他进程需要RAM时,可能会将其分页到辅助内存。基本上,您可以假设堆栈是由OS管理的内存块,通过在辅助内存,RAM,缓存等之间移动来优化最佳读/写时间。

我主要在windows上工作,上面的语句适用于windows。我不确定其他操作系统。

答案 1 :(得分:1)

是的,当您需要临时存储时使用堆栈。这可能就像函数持续时间的存储一样简单,或者当你用完寄存器并且需要驱逐一个寄存器来重新利用它时提到它。

不要仅仅了解指令集/硬件的工作原理。通常称为push和pop,这些指令通常采用寄存器,通常是专用的堆栈指针寄存器,它包含ram中的地址。当推送发生时,该寄存器中的地址(堆栈指针)用于将该数据写入/推入ram,并且相应地调整堆栈指针寄存器内容(ram地址)。这一切都是由基于使用该指令的硬件完成的。另一种方式是,基于堆栈指针地址和pop指令的风格读取ram,ram的内容根据pop指令的风格放置在某处,并相应地调整堆栈指针寄存器内容。

使用什么ram地址?为什么?这就是我认为你在问的问题。嗯,这通常取决于系统设计人员,人们在系统中占用ram并在程序,数据,堆和堆栈之间进行划分。通常你会看到,如果你有一个线性的ram块你正在使用该ram的较低(地址)部分有程序本身,指令,就在那之上是该程序使用的数据,然后是剩余的记忆是这个没有人的土地。从内存的底部到顶部通常是堆的所在。编译器不知道malloc需要多少堆,只有程序员才需要。堆栈通常从这个开放空间的顶部开始并向下扩展,你在堆栈上推送的每个东西都被推到你在堆栈上推送的最后一个东西的底部并且它会向下扩展。堆栈和堆冲突存在非常真实的风险,这是程序员的工作(通常,一些语言/编译器会烧掉大量额外的代码,以便在您提出要求时尝试阻止它)。因此,通常堆栈与数据和bss区域隔壁的堆位于同一位置。 Certaily情况并非总是这样,在某些嵌入式系统中,你的程序在rom中,而数据和堆(如果你足够勇敢/疯狂到足以在嵌入式系统中使用堆)都在ram的一部分中,而堆栈可能在ram的单独部分中,而不是在data / heap ram旁边。也许是因为那个公羊比较快。一个很好的例子就是游戏玩家的进步,有一个256K的内存是片外的,而且通用速度较慢,片上内部的32k速度要快得多,这是放置堆栈(和速度关键代码)的好地方。包含程序本身的rom(加上一些硬件使其不会慢慢变慢)。有时你有像6502这样的处理器,其中堆栈指令只在ram的特定区域上运行,我认为在地址0x200处有256个位置或类似的东西,以这种方式设计到硬件中。芯片没有关闭。一些处理器,如ARM模式下的ARM,没有堆栈指针,可以使用任何寄存器,并且没有推送和弹出,它们是通用加载和存储指令的别名。按照惯例,编译器通常将特定寄存器保留/用作堆栈指针,但不像其它处理器那样需要它。授予拇指和拇指2等其他手臂指令集,减少指令大小,删除通用性质,并将传统r13硬编码为堆栈指针,因此对于那些模式你没有选择,你得到r13而你不使用通用指示您专门使用推送和弹出说明。

将所有这些放在Windows或Linux或其他多线程/任务操作系统世界中。没有任何改变,处理器不会仅仅为操作系统重新设置其指令集,无论您在该处理器上运行什么软件,都可以获得相同的指令集。操作系统的作用是使用MMU,使每个程序都具有在程序空间,数据空间,堆和堆栈中存在相对较小的固定内存量的错觉。 MMU为程序提供了所有具有相同地址空间的错觉,例如所有程序可能认为它们的程序从地址0x8000开始,你不能让所有程序都在一个地址,0x8000是一个虚拟地址,mmu将它映射到物理地址,每个程序都有一组不同的物理地址。当操作系统切换到下一个任务/程序/线程时,它会保存您的堆栈指针和其他寄存器,并加载下一个程序的寄存器(勾选mmu)并在处理器上给它一些时间,它也认为它有自己的平面内存空间,包括程序空间,数据空间,堆和堆栈。

关于堆栈的大量理解是查看指令集。故事的其余部分是如何选择堆栈指针的地址,它可以根据平台,操作系统和编译器而变化。在很多情况下,链接描述文件或链接进程具有用户定义的规则。您作为程序员/用户可能没有意识到您可以控制它,因为您可能只使用编译器默认值,但对于流行的编译器(井链接器),您可以选择更改它。