一、栈的基本概念栈有两个基本的操作:入栈和出栈。 8086CPU提供的栈机制8086CPU提供入栈和出栈指令: (最基本的) push和pop指令也可以在内存和寄存器传输数据(以栈的形式) 示例:
那么问题来了,在执行push和pop的时候,如何知道哪个单元是栈顶单元? 8086CPU中,有两个寄存器:
任意时刻,SS:SP指向栈顶元素。 二、push和pop指令push 指令的执行过程在执行push ax指令时,主要做了一下2件事 pop 指令的执行过程在执行pop ax指令时,主要做了一下2件事 当栈为空的时候,SS:SP指向最高地址空间的下一位任意时刻,SS:SP 指向栈顶元素,当栈为空的时候,栈中没有元素,也就不存在栈顶元素,所以SS:SP 只能指向栈的最底部单元下面的单元,该单元的偏移地址为栈最底部的字单元的偏移地址+2,栈最底部字单元的地址为1000:000E,所以栈空时,SP=0010H。 栈顶超界的问题(简单了解就好,我们又不做黑客)原因:SS和SP只记录了栈顶的地址,依靠SS和SP可以保证在入栈和出栈时找到栈顶。 上面我说了,CPU并不知道这段是代码段,数据段还是栈段,都是人为设定的所以加入这个栈空了,我们继续pop,它就会把其它段的数据pop出。所以非常危险 解决办法:一个很NC的办法,就是我们在编程的时候要自己操心栈顶超界的问题 ,要根据可能用到的最大栈空间,来安排栈的大小,防止入栈的数据太多而导致的超界;执行出栈操作的时候也要注意,以防栈空的时候继续出栈而导致的超界。 push和pop指令具体可以操作
示例: 1、将10000H~1000FH 这段空间当作栈,初始状态是空的,将 AX、BX、DS中的数据入栈。 2、编程 (1)将10000H~1000FH 这段空间当作栈,初始状态是空的; 3、编程: (1)将10000H~1000FH 这段空间当作栈,初始状态是空的;
4、补全下面的代码,完成同样的功能:在10000H处写入字型数据2266H。 __________
栈段上面说过我们可以定义一段内存单元为代码段,数据段或栈段。 我们可以将一个段空间当做一个栈段,一个栈段最大64K,因为16位CPU的偏移地址最大为2^16B,如果超出FFFF它会重新变成0(FFFF+1=0000,1被抛弃了)。 CPU是如何判断哪块是什么段的? 我们可以将一段内存定义为一个段,用一个段地址指示段,用偏移地址访问段内的单元。这完全是我们自己的安排。 对于代码段,将它的段地址放在 CS中,将段中第一条指令的偏移地址放在IP中,这样CPU就将执行我们定义的代码段中的指令; 对于栈段,将它的段地址放在SS中,将栈顶单元的偏移地置放在 SP 中,这样CPU在需要进行栈操作的时候,比如执行 push、pop 指令等,就将我们定义的栈段当作栈空间来用。 可见,不管我们如何安排 ,CPU 将内存中的某段内存当作代码 ,是因为CS:IP指向了那里;CPU将某段内存当作栈 ,是因为 SS:IP 指向了那里。 |
|