如何获取存储在堆栈中的变量?

时间:2013-04-10 22:02:08

标签: variables memory operating-system stack

编程时(例如,在C中),很多变量都保存在堆栈中。 堆栈是FIFO数据结构,我们只能弹出堆栈的最高值。

假设我有100个变量存储在堆栈中,我想得到其中一个变量的值,它不在堆栈的顶部。 我怎么得到它?操作系统是否会弹出堆栈中较新的所有变量,直到获得所需变量,然后将所有变量推回到内部? 或者操作系统是否可以采用不同的方式处理堆栈内的变量?

由于

2 个答案:

答案 0 :(得分:2)

予。操作系统不会直接对您的变量执行任何操作。

II。不要将堆栈视为物理堆栈(原因很简单:它不是一个)。可以直接访问堆栈的元素,编译器会生成执行此操作的代码。谷歌“堆栈指针相对寻址”。

答案 1 :(得分:2)

在C语言中使用的堆栈不是典型的LIFO。它被称为堆栈,因为它以类似的方式用于LIFO:当调用过程时,新帧被推入堆栈。框架通常包含局部变量和簿记信息,例如返回的位置。类似地,当一个过程返回时,它的框架将从堆栈中弹出。

这没有什么神奇之处。编译器(不是操作系统)分配一个寄存器用作 stack pointer - 让我们称之为SP。按照惯例,SP指向下一个空闲堆栈字的内存位置:

+----------------+ (high address)
|   argument 0   |
+----------------+
|   argument 1   |
+----------------+
| return address |
+----------------+
|    local 0     |
+----------------+
|    local 1     |
+----------------+                  +----+    
|    free slot   |  <-------------- | SP |
+----------------+ (low address)    +----+

要将值压入堆栈,我们会执行类似的操作(在伪装配中):

STORE [SP], 42 ; store the value 42 at the address where SP points
SUB SP, 1      ; move down (the stack grows down!) to the next stack location

其中符号[SP]被读为&#34; SP指向的存储器单元的内容&#34;。某些体系结构,尤其是x86,提供了push指令,可以执行存储和减法操作。要在堆栈上弹出(并丢弃) n 顶部值,我们只需将 n 添加到SP *。

现在,假设我们想要访问上面的local 0字段。如果我们的CPU具有base+offset寻址模式,那就足够了!假设SP指向空闲时段,如上图所示。

 LOAD R0, [SP+2] ; load "local 0" into register R0

注意我们没有首先需要从堆栈中弹出local 0,因为我们可以使用堆栈指针的偏移来引用任何字段。

根据编译器和机器架构,可能有另一个寄存器指向本地和参数(或其附近)之间的区域。该寄存器通常称为frame pointer,在堆栈指针移动时保持固定。

我想强调的是,通常情况下,操作系统根本不涉及堆栈操作。内核分配初始堆栈,并可能监视其增长,但将值推送和弹出到用户程序。

*为简单起见,我假设机器字大小为1字节,这就是我们从SP中减1的原因。在32位机器上,将一个字推入堆栈意味着减去(至少)四个字节。