汇编语言_06

2017-07-17  本文已影响21人  番薯大佬


push ax


push ax 的执行由以下两个步骤完成

pop ax


pop ax的执行过程和push ax刚好相反,由以下两步完成

思考
如果将10000H 到 1000FH 这段空间当做栈,初始状态栈是空的,此时,SS=1000H,SP=?思考后看分析。


栈空,SS:SP执行栈控件最高地址单元的下一个单元


结果

栈顶超界
push


pop


上面描述了执行push、pop指令时,发生的栈顶超界问题。可以看到,当栈满的时候再使用push指令入栈,或栈空的时候再使用pop指令出栈,都将发生栈顶超界问题。

栈顶超界是危险的,因为我们既然将一段空间安排为栈,那么在栈空间之外的空间里
很可能存放了具有其他用途的数据、代码等,这些数据、代码可能是我们自己程序中的,也可能是别的程序中的(毕竟一个计算机系统中并不是只有我们自己的程序在运行)。但是由于我们在入栈、出栈时的不小心,而将这些数据、代码意外地改写,将会引发一连串的错误。

我们当然希望CPU可以帮我们解决这个问题,比如说在CPU中有记录栈顶上限和栈底的寄存器,我们可以通过填写这些寄存器来指定栈空间的范围,然后,CPU在执行push指令的时候靠检测栈顶上限寄存器,在执行pop指令的时候靠检测栈底寄存器保证不会超界。

不过,对于8086CPU,这只是我们的一个设想(我们当然可以这样设想,如果CPU是我们设计的话,这也就不仅仅是一个设想)。实际 的情况是,8086CPU中并没有这样的寄存器。

8086CPU不保证我们对栈的操作不会超界。这也就是说,8086CPU只知道栈顶在何处(由SS:SP指示),而不知道我们安排的栈空间有多大。这点好像CPU只知道当前要执行的指令在何处(由CS:IP指示),而不知道要执行的指令是多少。从这两点上我们可以看出8086CPU的工作机理,它只考虑当前的情况:当前的栈顶在何处,当前要执行的指令是哪一条。

我们在编程的时候要自己操作栈顶超界的问题,要根据可能用到的最大栈空间,来安排栈的大小,防止入栈的数据太多而导致的超界;执行出栈操作的时候也要注意,以防止栈空的时候继续出栈而导致的超界。

push&pop汇编
push 和 pop 指令的格式可以是如下形式

指令 说明
push 寄存器 将一个寄存器的数据入栈
pop 寄存器 出栈,用一个寄存器接收出栈的数据
push 段寄存器 将一个段寄存器中的数据入栈
pop 段寄存器 出栈,用一个段寄存器接收出栈的数据
push 内存单元 将一个内存字单元处的字入栈
pop 内存单元 出栈,用一个内存字单元接收出栈的数据
mov ax,1000H mov ds,ax 内存单元的段地址要放在ds中
push [0] 将1000:0处的字压入栈中
pop [2] 出栈,出栈的数据送入1000:2处

注意

编程练习

mov ax,1000H
mov ss,ax
mov sp,0010H

mov ax,001AH
mov bx,001BH

push ax
push bx
pop ax
pop bx

栈段

段总结

  • 我们可以用一个段存放数据,将它定义为"数据段"

对于数据段,将它的段地址放在DS中,用mov、add、sub等访问内存单元的指令时,CPU就将我们定义的数据段中的内容当作数据来访问;
对于代码段,将它的段地址放在CS中,将段中第一条指令的偏移地址放在IP中,这样CPU就将执行我们定义的代码段中的指令;
对于栈段,将它的段地址放在SS中,将栈顶单元的偏移地址放在SP中,这样CPU在需要进行栈操作的时候,比如执行push、pop指令等,就将我们定义的栈段当作栈空间来用。

练习


练习1
练习1-答案
练习2
练习2-答案
上一篇下一篇

猜你喜欢

热点阅读