文章目录[隐藏]
现今的CPU中都有栈的设计,8086CPU也不例外。8086CPU提供相关的指令来以栈的方式访问内存空间。这意味着,在基于8086CPU编程的时候,可以将一段内存当作栈
来使用。
8086CPU提供入栈和出栈指令,最基本的两个是PUSH(入栈)
和POP(出栈)
。如,push ax表示将寄存器ax中的数据送入栈中,pop ax表示从栈顶取出数据送入axe8086CPU的入栈和出栈操作都是以字为单位进行的。
下面举例说明,我们可以将10000H-1000FH这段内存当作栈来使用。
图3.9描述了下面一段指令的执行过程。
mov ax, 0123H push ax 2266H mov bx, 1122H push bx mov cx, push cx pop ax pop bx pop cx
注意,字型数据用两个单元存放,高地址单元存放高8位,低地址单元存放低8位。
读者看到图3.9所描述的push和pop指令的执行过程,是否有一些疑惑?总结一下,大概是这两个问题。
其一,我们将10000H}1000FH这段内存当作栈来使用,CPU执行push和pop指令时,将对这段空间按照栈的后进先出的规则进行访问。但是,一个重要的问题是,CPU如何知道10000H-1000FH这段空间被当作栈来使用?
其二,push ax等入栈指令执行时,要将寄存器中的内容放入当前栈顶单元的上方,成为新的栈顶元素;pop ax等指令执行时,要从栈顶单元中取出数据,送入寄存器中。显然,push, pop在执行的时候,必须知道哪个单元是栈顶单元,可是,如何知道呢?
这不禁让我们想起另外一个讨论过的问题,就是,CPU如何知道当前要执行的指令所在的位置?我们现在知道答案,那就是CS, IP中存放着当前指令的段地址和偏移地址。现在的问题是:CPU如何知道栈顶的位置?显然,也应该有相应的寄存器来存放栈顶的地址,8086CPU中,有两个寄存器,段寄存器SS和寄存器SP,栈顶的段地址存放在SS中,偏移地址存放在SP中。任意时刻,SS:SP指向栈顶元素
。push指令和pop指令执行时,CPU从SS和SP中得到栈顶的地址。
现在,我们可以完整地描述push和pop指令的功能了,例如push ax
push ax的执行,由以下两步完成。
(1) SP=SP-2 SS:SP指向当前栈顶前面的单元,以当前栈顶前面的单元为新的栈顶;
(2)将ax中的内容送入SS:SP指向的内存单元处,SS:SP此时指向新栈顶。
图3.10描述了8086CPU对push指令的执行过程。
从图中我们可以看出,8086CPU中,入栈时,栈顶从高地址向低地址方向增长。
问题3.6
如果将10000H- 1000FH这段空间当作栈,初始状态栈是空的,此时,SS=1000H,SP=? 思考后看分析。
分析:
SP=0010H,如图3.11所示。
将10000H-1000FH这段空间当作栈段,SS=1000H,栈空间大小为16字节,栈最底部的字单元地址为1000:000E。任意时刻,SS:SP指向栈顶,当栈中只有一个元素的时候,SS=1000H-SP=000EH。栈为空,就相当于栈中唯一的元素出栈,出栈后,
SP=SP+2 SP原来为000EH,加2后SP=l0H,所以,当栈为空的时候,SS=1000H0
SP=l0H
换一个角度看,任意时刻,SS:SP指向栈顶元素,当栈为空的时候,栈中没有元素,也就不存在栈顶元素,所以SS:SP只能指向栈的最底部单元下面的单元,该单元的偏移地址为栈最底部的字单元的偏移地址+2,栈最底部字单元的地址为1000:000E,所以栈空时,SP=0010H
接下来,我们描述pop指令的功能,例如pop ax
pop ax的执行过程和push ax刚好相反,由以下两步完成。
(1)将SS:SP指向的内存单元处的数据送入ax中;
(2) SP=SP十2 SS:SP指向当前栈顶下面的单元,以当前栈顶下面的单元为新的栈顶。
图3.12描述了8086CPU对pop指令的执行过程。
注意,图3.12中,出栈后,SS:SP指向新的栈顶1000EH ,pop操作前的栈顶元素, 1000CH处的2266H依然存在,但是,它已不在栈中。当再次执行SS:SP移至1000CH,并在里面写入新的数据,它将被覆盖。