内存中的栈

操作系统会为进程(正在运行的应用程序)分配内存空间用于存放程序在执行过程中需要的代码和数据。根据内存的使用方式不同,会把内存划分成几个具有不同功能的区域。其中一块区域叫做堆栈(也被称为栈),它和数据结构中的栈一样具有后进先出的性质。堆栈用于记录函数在调用过程中产生的信息,比如函数局部变量和参数等信息。本文后面提到的均指的是内存中的堆栈

CPU提供了对栈内存进行压栈(push)和出栈(pop)的指令,同时还有一个叫做栈指针(sp)的寄存器用来保存栈顶位置的内存地址栈内存是从高地址低地址空间发展,这一点跟正常的思维习惯有点不一样,也就是说当你向push一个新的数据时,栈的地址会变小。

为了方便表示本文后面的所有栈结构图中的每个格子都是8个字节 ,同时我们也假设push和pop指令每次操作8个字节

下图是一个大小为80个字节(图中每个格子是8个字节)的,地址范围是0~79。栈指针指向栈顶的位置:

后面提到的指令均是类似于C语言的伪代码,只是用来描述栈的变化过程。

压栈

压栈时把栈指针低地址移动也就是减小栈指针,然后把数据写入到以栈指针开始的内存中。

例如要把数值123压入到栈中,对应的指令就是:

push(123);

它的效果等价于下面这两条指令:

sp = sp - 8;
*sp = 123;

由于我们假设push指令每次操作8个字节,所以第1条指令先把sp(栈指针)向低地址移动8个字。然后第2条指令再把数据写入到以sp开始的那8个字节的内存中。*sp表示的是栈指针所指向的那块内存空间,而不是栈指针本身。

栈变化过程:

出栈

出栈时先取出以栈指针开头的8个字节(我们假设pop每次操作8个字节)的数据,再把栈指针向高地址移动8个字节也就是增加栈指针。

把压栈例子中栈顶的数据出栈至变量rax中,对应的指令:

pop(rax);

它的效果等价于下面这两条指令:

rax = *sp;
sp = sp + 8;

先把以栈指针开始的8个字节的数据放入变量rax中,由于压栈例子中压入的是123,所以此时出栈的数据也是123,最后把栈指针向高地址移动8个字节。

栈变化过程:

results matching ""

    No results matching ""