Introduction
当一段程序运行时,会开辟出一段连续的地址空间,被称为栈。
这是一个从高地址开始生成的栈。

SP (Stack pointer) 是一个专用的寄存器,用来保存栈的栈顶地址。所有低于 SP 地址的数据都是 Garbage,等于 SP 地址以及高于 SP 地址所存储的数据都是合法的数据。
Stack bottom 是整个栈可以使用的最大的地址,当这个栈初始化的时候 SP 指向栈底。
Stack limit 是整个栈最小的地址,当 SP 比 stack limit 更小的时候,栈就溢出了。
Push & Pop
Push: 增加 SP 地址,将数据存储至 SP 当前所指的地址中。

Pop: 读取出当前栈顶所存储的数据,然后将减少 SP 地址。

Stack & Function
当一个函数被调用的时候,会分配一块栈空间给函数,叫做(栈帧) stack frame,直到函数调用完成,栈帧被回收。
Stack frame: 栈帧相当于一个函数的运行环境,它包括本地变量,函数参数,返回值等等。
例如 C 中有一个 foo1 函数,如果 foo1 中调用一个函数叫做 foo2,调用栈如下所示:

Previous frame 指的是 foo1 的栈帧,Current frame 指的是 foo2 的栈帧。同时会有一个新的寄存器 FP (Frame pointer) 存储调用者(这里是 foo1)FP 的地址。通过向高地址或者低地址偏移 FP,foo2 可以读取到输入参数以及本地变量。
创建 foo2 栈帧的过程应该是这样的:先往 foo1 栈帧中压入 foo2 需要接受的参数(输入参数),再压入 return address,指的是结束调用 foo2 之后应该调用的指令的地址。随后创建 foo2 的栈帧压入本地变量等等。
一旦 foo2 调用结束,foo2 的栈帧被弹出整个调用栈,随后将 FP 恢复至调用者(foo1)的 FP,SP 指向 foo1 的 return address(此时的栈顶),执行下一条指令。
网友评论