汇编语言 3.8 3.9 栈顶超界问题 push pop

3.8 栈顶超界问题

之前在3.6,3.7我们知道了8086CPU用SS和SP指示栈顶的地址,并提供push和pop指令实现入栈和出栈。在出栈或者入栈时,可能会出现超出栈空间的情况,如下所示:

push超出栈
pop超出栈

这里我们引入一个新的概念,栈空间。

栈顶超界是危险的,因为栈空间之外的空间里很可能存放了具有其他用途的数据。CPU在执行push指令的时候考检测栈顶上线寄存器、在执行pop指令时候检测栈底寄存器保证不会超界。

但8086CPU不具有这个功能,它只知道栈顶在何处(SS:SP指示),而不知道我们安排的栈空间的大小。

在编程时要自己操心栈顶超界问题,要根据可能用到的最大栈空间,来安排栈的大小。

3.9 push pop指令

push 和pop指令是可以在寄存器和内存(栈空间也是内存空间的一部分)。格式形式如下:

1 针对寄存器

push 寄存器   ;将一个寄存器中的数据入栈
pop 寄存器 ;出栈,用一个寄存器接收出栈的数据

eg.

push ax
pop ax

2 针对段寄存器

push 段寄存器  ;将一个段寄存器中的数据入栈
pop 段寄存器 ;出栈,用一个段寄存器接收出栈数据

eg.

push ds
pop es

3 针对内存单元

push 内存单元  ;将一个内存字单元处的字入栈(注意:栈操作都是以字为单位)
pop 内存单元 ; 出栈,用一个内存字单元接收出栈的数据

eg.

push [0] ;入栈1000:0处字
pop [2] ;出栈ds:2处

另外, 有个注意事项:

关于如何在10000H处写入字型数据2266H

代码如下:

mov ax, 1000H
mov ss, ax
mov sp, 2 <-++->
mov ax, 2266H
push ax

注意<-++->处,之所以在SP上规定为2, 因为push命令是在栈顶上压入数据,而如果我们要在栈顶上压入新的数据就得先在SP寄存器中先减2。否则如果不指定sp 为2,就无法准确指定10000H处。我们来画一个栈,

| 10000H |
| 10001H |
| 10002H |
| … |
| 1000CH |
| 1000DH |
| 1000EH |

1000FH
10010H

1000FH为栈的最底处,当SS:SP指针指向10010H时,为空栈。而当我们问题中想要在10000H处push数据,所以我们必须首先调整sp到2(10002H处),这样进行push时候第一步先执行$SP=SP-2$时,就将指针从10002H调整到了10000H处。

另外一个需要注意的事项,十分重要,但很好理解:

出栈的顺序要和入栈的顺序相反