3.6(3.7)栈与栈机制
1.栈是一种具有特殊访问方式的存储空间,对于存储的数据先进后出(先放入的最后取出,像往狭窄的瓶子里放东西再取出)
2.8086CPU提供相关的指令来以栈的方式访问内存
3.入栈(push指令)是指将一个新的元素放到栈顶,出栈(pop指令)即从栈顶取出一个元素。入栈和出栈的操作都是以字为单位来进行。
mov ax,0123H 22 ----- 1000AH
push ax (0123H) 11 -----1000BH
mov bx,2266H 66 ------1000CH
push bx (2266H) ====> 22 ------1000DH
mov cx,1122H 23 ------1000EH
push cx (1122H) 01 ------1000FH
pop ax pop处理后
pop bx ===> ax=1122H,bx=2266H,cx=0123H
pop cx
4.cpu如何找到栈顶位置?
cpu从段寄存器SS(存放段地址)与SP(存放偏移地址)寻找栈顶位置。任何时刻,SS:SP指向栈顶元素。
push ax指令:
(1)SP=SP-2,SS:SP指向当前栈顶前面的单元,并以此为新栈顶。
(2)将ax中的内容送入SS:SP指向的内存单元中
即push 指令是先移动栈顶位置再填入数据
栈空,SS
pop 指令(先送值,再移动栈顶)
(1)将SS:SP指向的内存单元处的数据送入指定寄存器中
(2)SP=SP+2,SS :SP 指向当前栈顶下面的单元,以当前栈顶下面的单元位新单元的栈顶。
注意:执行pop指令后,pop出去的数据值仍存在 ,但不在栈中,当再次执行push等入栈指令后,Pop出去的数据位置,写入新的数据,元数据被覆盖。
3.8(3.9)栈顶超界问题
1.栈顶超界问题即执行Push指令或pop指令后,数据覆盖到栈之外的部分
2.push,pop指令还有如下形式:
(1)push/pop 寄存器 //将一个 寄存器中的数据入栈(用一个寄存器接受出栈数据)
(2)push/pop 段寄存器 //将一个段寄存器的数据入栈(用一个段寄存器接受出栈数据)
(3)push/pop 内存单元 //将一个内存字单元处的字入栈(用一个内存字单元接受出战数据)
3.编程练习:将10000H~1000FH这段内存当作栈。初始栈为空,将AX,BX,数据写入然后将AX,BX数据清零,最后从栈中恢复Ax,BX的值。
mov ax,1000H
mov ss,ax //不能直接向SS段寄存器直接写值,以ax为中间寄存器
mov sp,0010H //设置偏移地址,栈为空,所以sp 为0010H
push ax
push bx
sub ax,ax //也可以是mov ax,0 但是sub指令实现机器码为2个字节,mov 为三个字节
sub bx,bx
pop bx //原ax寄存器中的值再栈的下方,所以先pop出bx的值
pop ax
注意:1.pop/push指令访问的内存单元的地址不是再指令中给出,而是由SS:SP指出。
2.push/pop等栈操作指令,修改的只是SP,所以栈顶变化范围是0~FFFFH
3.SS :SP 中分别存放栈顶的段地址和偏移地址。任意时刻,SS:SP指向栈顶元素。
4.8086cpu只记录栈顶,栈空间大小要自己管理。
4.关于cpu 如何判定我么把哪一段内存当作数据段,哪一段内存当作栈段等的说明
(1) 一段内存可以被当成数据段,也可以被当成代码段,也可以被当成栈段,甚至三者都是。
(2)对于数据段,将他的段地址放在DS中,用mov,add,sub 指令等访问内存单元是,cpu 将我们定义的数据段中的内容当作数据访问。
(3)对于代码段,将他的地址放在CS中,将段中第一条指令的偏移地址放在IP中,这杨cpu 就会执行我们定义的代码段中的指令。(cpu 将哪里当作代码段使用,是因为CS:IP指向那里)。
(4) 对于栈段,将他的地址放到SS中,将栈顶的偏移地址放在SP中,这样cpu 在执行栈操作的时候(比如pop,push 指令)将我们定义的栈段当作栈空间使用。