前言:
栈。
目录:
栈:
栈是一种具有特殊的访问方式的存储空间。它的特殊性就在于,最后进入这个空间的数据,最先出去。
入栈和出栈指令:
push 入栈
比如,push ax
表示将寄存器 ax 中的数据送入栈中
pop 出栈
比如,pop ax
表示从栈顶取出数据送入 ax
那么问题来了,CPU 如何知道当前要执行的指令所在位置
那就是 CS、IP 中存放着当前指令的段地址和偏移地址
现在CPU如何知道栈顶的位置?
很显然也应该有相应的寄存器来存放栈顶的地址
这两个寄存器分别是 段寄存器 SS 和 寄存器 SP
栈顶的段地址存放在 SS 中,
偏移地址存放在 SP 中
任意时刻,SS:SP 指向栈顶元素 。
栈空:
如果将 10000H-1000FH 这段空间当作栈,初始状态栈是空的,
此时,SS=1000H ,SP=?
如图所示,将 10000H-1000FH 这段空间当作栈,SS=1000H ,栈空间大小为16字节,
栈最底部的字单元地址为 1000:000E 。任意时刻,SS:SP 指向栈顶,
当栈中只有一个元素的时候,SS=1000H ,SP=000EH 。栈为空,
就相对于栈中唯一的元素出栈,出栈后,SP=SP+2 ,SP 原来为 000EH ,加2后 SP=10H ,
所以,当栈为空的时候,SS=1000H ,SP=10H 。
换一个角度看,任意时刻,SS:SP 指向栈顶元素,当栈为空的时候,栈中没元素,
也就不存在栈顶元素,所以 SS:SP 只能指向栈的最底部单元下面的单元,
该单元的偏移地址为栈最底部的字单元的 偏移地址+2 ,
栈最底部字单元的地址为 1000:000E ,所以栈空时,SP=0010H。
栈顶超界的问题:
栈顶超界 简单的讲就是有一段栈空间,
如果 push 或者 pop 数据过多将会超出这段空间
push 超界
将 10010H-1001FH 当作栈空间,该栈空间容量为16字节(8字节),初始状态为空,
SS=1000H 、SP=0020H ,SS:SP 指向 10020H ;
每执行一次 push ax ,SP=SP-2 ,
在执行 8次 push ax 后,向栈中压入8个字,栈满,SS:SP 指向 10010H ;
再次执行 push ax 后 sp=sp-2,SS:SP 指向 1000EH ,栈顶超出了栈空间,
ax 中的数据送入 1000EH 单元处,将栈空间外的数据覆盖。
pop 超界
将 10010H-1001FH 当作栈空间,该栈空间容量为16字节(8字节),初始状态为空,
SS=1000H、SP=0010H,SS:SP 指向10010H;
在执行 8次 push ax
后,向栈中弹出8个字,栈空,SS:SP 指向 10020H;
再次执行 push ax 后 sp=sp+2,SS:SP 指向 10022EH,栈顶超出了栈空间,
此后,如果再执行push指令,10020H、10021H 中的数据都将被覆盖。
总结
栈。