汇编语言入栈出栈PUSH和POP指令

push和pop指令的格式可以是如下形式:

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

当然也可以是如下形式:

push     段寄存器          ;将一个段寄存器中的数据入栈
pop      段寄存器          ;出栈,用一个段寄存器接收出栈的数据
push和pop也可以在内存单元和内存单元之间传送数据,我们可以:
push     内存单元          ;将一个内存字单元处的字入栈(注意:栈操作都是以字为单位)
pop      内存单元          ;出栈,用一个内存字单元接收出栈的数据

比如

mov ax,1000H   
mov ds,ax      ;内存单元的段地址要放在ds中
push [0]        ;将1000:。处的字压入栈中
pop  [2]        ;出栈,出栈的数据送入1000:2处

指令执行时,CPU要知道内存单元的地址,可以在push, pop指令中只给出内存单元的偏移地址,段地址在指令执行时,CPU从ds中取得。

问题3.7

编程,将10000H-1 000FH这段空间当作栈,初始状态栈是空的,将AX, BX, DS中的数据入栈。
分析代码如下:

mov   ax,1000H
mov   ss,aX        ;设置栈的段地址,SS=1000H,不能直接向段寄存器SS中送入
                    ;数据,所以用ax中转。
mov  sp,0010H       ;设置栈顶的偏移地址,因栈为空,所以sp=OOlOH。如果
                    ;对栈为空时SP的设置还有疑问,复习3.,节、问题3.6
                    ;上面的3条指令设置栈顶地址。编程中要自己注意栈的大小。
push  ax
push  bX
push  ds

问题3.8

编程
(1)将1 0000H-1000FH这段空间当作栈,初始状态栈是空的;
(2)设置AX=001 AH , BX=001 BH
(3)将AX, BX中的数据入栈;
(4)然后将AX, BX清零;
(5)从栈中恢复AX, BX原来的内容。
分析代码如下:

mov  ax,1000H
mov  ss,aX
m0V  sp,0010H   ;初始化栈顶,栈的情况如图3.15(a)所示

mov  ax,001AH
mov  bx,001BH

push  aX
push  bx      ;ax. bx入栈,栈的情况如图3.15 (b)所示

sUb  ax,ax   ;将ax清零,也可以用mov ax,0,
             ;sub ax,ax的机器码为2个字节,
             ;mov ax,。的机器码为3个字节。
sub bx,bx
pop  bx      ;从栈中恢复ax,  bx原来的数据,当前栈顶的内容是bx
PoP  dx      ;中原来的内容:OO1BH} ax中原来的内容OOIAH在栈顶
             ;的下面,所以要先pop bx,然后再pop axo

511遇见

从上面的程序我们看到,用栈来暂存以后需要恢复的寄存器中的内容时,出栈的顺序要和入栈的顺序相反,因为最后入栈的寄存器的内容在栈顶,所以在恢复时,要最先出栈。

问题3.9

编程
(1)将10000H-1 000FH这段空间当作栈,初始状态栈是空的:
(2)设置AX=001 AH , BX=001 BH
(3)利用栈,交换AX和BX中的数据。
分析代码如下:

mov   ax,1000H
moV   ss,ax
mov   sp,0010H     ;初始化栈顶,栈的情况如图3.16(a)所示

mov ax,001AH
mov bx,001BH
push ax
push bx      ;ax. bx入栈,栈的情况如图3.16 (b)所示
pop ax       ;当前栈顶的数据是bx中原来的数据:001BH;
             ;所以先pop ax, ax=00O1BH;
pop bx       ;执行pop ax后,栈顶的数据为ax原来的数据;
             ;所以再pop bx, bx=00lAH;

511遇见

问题3.10

如果要在10000H处写入字型数据2266H,可以用以下的代码完成:

mov   ax,1000H
mov   ds,ax
mov   ax,2266H
moV   [0],ax

补全下面的代码,使它能够完成同样的功能:在10000H处写入字型数据2266H
要求:不能使用“mov内存单元,寄存器”这类指令。
分析
我们来看需补全代码的最后两条指令,将ax中的2266H压入栈中,也就是说,最终应由push ax将2266H写入1 0000H处。问题的关键就在于:如何使push ax访问的内存单元是1 0000H
push ax是入栈指令,它将在栈顶之上压入新的数据。是,先将记录栈顶偏移地址的SP寄存器中的内容减2,使得然后再将寄存器中的数据送入SS:SP指向的新的栈顶单元。
一定要注意:它的执行过程SS:SP指向新的栈顶单元,
所以,要在执行push ax之前,将SS:SP指向10002H(可以设SS=1000H ,SP=0002H),这样,在执行push ax的时候,CPU先将SP=SP-2,使得SS:SP指向10000H,再将ax中的数据送入SS:SP指向的内存单元处,即10000H处
完成的程序如下:

mov  ax,1000H
mov  ss,aX
mov  sp, 2
mov  aX,2266H
push ax

从问题3.10的分析中可以看出,push, pop实质上就是一种内存传送指令,可以在寄存器和内存之间传送数据,与mov指令不同的是,push和pop指令访问的内存单元的地址不是在指令中给出的,而是由SS:SP指出的。同时,push和pop指令还要改变SP中的内容。
我们要十分清楚的是,push和pop指令同mov指令不同,CPU执行mov指令只需一步操作,就是传送,而执行push, pop指令却需要两步操作。执行push时,CPU的两步
操作是:
先改变SP,后向SS:SP处传送。
执行pop时,CPU的两步操作是:
先读取SS:SP处的数据,后改变SP
注意
注意,push, pop等栈操作指令,修改的只是SP。也就是说,栈顶的变化范围最大为:O-FFFFH
提供:SS, SP指示栈顶;改变SP后写内存的入栈指令;读内存后改变SP的出栈指令。这就是8086CPU提供的栈操作机制。

栈的综述

(1)8086CPU提供了栈操作机制,方案如下:
在ss、sp中存放栈顶的段地址和偏移地址
提供入栈和出栈指令,他们根据SS:SP指示的地址,按照栈的方式访问内存单元
(2) Push指令的执行步骤
①SP=SP-2;
②向S5:SP指向的字单元中送入数据。
(3)pop指令的执行步骆
①从SS:SP指向的字单元中读取数据:
②Sp=SP+2
(4)任意时刻SS: SP指向栈顶元素。
(5) 8086cPU只记录栈顶,一栈空间的大小我们要自己管理。
(6)用找来暂存以后需要恢复的寄存器的内容时,寄存器出栈的顺序要和入栈的顺序相反。
(7)push、pop实质上是一种内存传送指令,注意它们的灵活应用。


发布日期:

所属分类: 易语言 标签: