2012-01-06 139 views
0

就我所知,堆栈可用于存储数据,当您需要实现功能或只是用尽寄存器使用。我拥有的问题是通常使用的堆栈是什么内存。我感觉这取决于预取过程和其他因素。同样在什么时候堆叠被重新加载到RAM中。ASM堆栈使用

+0

你的问题不清楚 - 没有分配给堆栈的RAM的特定区域。阅读堆栈指针 – 2012-01-06 06:17:45

+0

堆栈是ram。如果您查看/ proc/self/maps(Linux),您可以看到虚拟内存的一部分映射到堆栈的虚拟内存旁边,以及映射到其他垃圾的内存。关于堆栈没有特别的。 – Lalaland 2012-01-06 06:18:07

回答

1

每个进程都有线程,每个线程都有一个堆栈。每个进程都有自己的空间,称为进程地址空间。线程在这个进程地址空间中分配它们的堆栈。这个空间是一个虚拟空间,也就是说一个进程获得4GB的进程空间,它可能并不总是在RAM上。当其他进程需要RAM时,它可能会被调出到辅助存储器。基本上,您可以假设堆栈是由操作系统通过在辅助内存,RAM,缓存等之间移动来管理的一块内存,以优化最佳读/写时间。

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

+0

是的,这是我正在寻找的答案。我不确定是否有一种方法可以确定您正在使用的特定进程的堆栈是否位于硬盘,RAM或缓存中,但是通过它的声音,没有其他控制重写OS如何处理内存分配。 – Blackninja543 2012-01-06 07:03:29

+0

@Blackninja - 堆栈使用非常频繁,所以它几乎总是在缓存中,并且很少在交换文件中。 – 2012-01-06 09:50:57

+0

对于正在运行的进程,堆栈(TOS)不应该是可交换的内存空间,因为页面错误需要使用正在运行的进程的/线程堆栈来启动相应的处理程序。但暂停进程的堆栈很可能会被换出,这取决于操作系统的结构。 – 2012-01-06 14:43:46

1

是的,当您需要临时存储时使用堆栈。这可能与在函数期间存储一样简单,或者当您用完寄存器并需要驱逐一个来重新调整它时提到。

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

什么ram地址被使用,为什么?我想你在问什么?那么这通常取决于系统设计人员,这些人在系统中采用ram并将其分配在程序,数据,堆和堆栈之间。通常你会发现,如果你有一个单线性的ram块,你正在使用那个ram的较低的(地址)部分,那么程序本身就是这样,指令就在那个之上,就是那个程序使用的数据,的记忆是这不男人的土地。从内存底部往顶部往往是堆的居住地。编译器不知道malloc需要多少堆,只有程序员才需要。堆栈通常从这个开放空间的顶部开始并向下生长,你推入堆栈的每一件东西都被推到堆栈上的最后一件东西的底部,并且它向下生长。堆栈和堆的碰撞是非常现实的风险,这是程序员的工作(通常,如果你问的话,一些语言/编译器会烧掉很多额外的代码以防止它)。因此,通常堆栈与数据和bss区域隔壁的堆共处一处。事实并非如此,在某些嵌入式系统中,你的程序是在ROM中,而数据和堆(如果你勇敢/足够疯狂以便在嵌入式系统中使用堆)在一部分内存中,堆栈可能会在一个单独的内存部分,而不是在数据/堆内存旁边。也许是因为那个ram比较快。一个很好的例子就是游戏进步,有一个256K内存,它是片外的,通用速度较慢,而内置32K的片内速度要快得多,这是放置堆栈(以及加速关键代码)的好地方。包含程序本身的ROM(带有一些硬件加速以使其不会非常慢)。有时候你会有像6502这样的处理器,堆栈指令只在RAM的特定区域上运行,我认为在地址0x200处有256个位置,或者类似于硬件那样的设计。芯片上没有关闭。一些处理器,如ARM模式下的ARM,没有堆栈指针,可以使用任何寄存器,并且不存在推送和弹出,它们是通用加载和存储指令的别名。按照惯例,特定的寄存器通常被编译器保留/使用,作为堆栈指针,但不像其他处理器那样需要它。授予像拇指和拇指2这样的其他手臂指令集,以减小指令大小以消除通用目的,并将常规r13硬编码为堆栈指针,因此对于那些您没有选择的模式,您将得到r13,并且您不使用通用目的您的指令专门使用推入和弹出式指令。

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

关于堆栈的大部分理解都在看指令集。这个故事的其余部分是如何选择堆栈指针的地址,它可以根据平台,操作系统和编译器而有所不同。在很多情况下,链接器脚本或链接过程都有一个用户定义的规则。作为程序员/用户,您可能没有意识到自己掌握了这一点,因为您可能只是使用编译器默认值,但对于流行的编译器(以及连接器),您可以选择更改它。