栈
基本指令 1 PUSH
对于push指令的执行
- SP = SP - 2, SS:SP指向当前栈顶前面的单元,以当前栈顶前面的单元为新的栈顶;
- 将ax中的内容送入SS:SP指向的内存单元处,SS:SP此时指向新栈顶
具体的图就不画了
基本指令 2 POP
关于pop指令的执行
- 将SS:SP指向的内存单元处的数据送入ax中
- SP = SP + 2, SS:SP 指向当前栈顶下面的单元,以当前栈顶下面的单元为新的栈顶。
注意: 栈里面的单元是以字为单位的(2个字节),字单元的地址是两个字节地址中的低地址
栈顶的超界问题
对于8086CPU不保证对栈的操作不会越界。也就是说,8086CPU只知道栈顶在何出(由SS:SP指示),而不知道我们安排的栈空间有多大。这点好像CPU只知道执行的指令在何出(由CS:IP指示),而不知道要执行的指令有多少。从这两点上我们可以看出8086CPU的工作机理,它只考虑当前的情况:当前的栈顶在何处、当前要执行的指令是哪一条
其他问题
寄存器清零
两种方式:
- sub ax,ax 机器码为2个字节
- mov ax,0 机器码为3个字节
内存空间
一段内存,可以既是代码的存储空间,又是数据的存储空间,还可以是栈空间,也可以什么也不是.关键在于CPU中寄存器的设置,即CS\IP\SS\SP\DS的指向。
我们可以用一个段来此存放数据,将它定义为 数据段
我们可以用一个段来此存放代码,将它定义为 代码段
我们可以用一个段来此存放栈,将它定义为 栈段
对于数据段,将它的段地址放在DS中,用mov、add、sub等访问内存单元的指令时,CPU就将我们定义的数据段中的内容当作数据来访问。
对于代码段,将它的段地址放在CS中,将段中第一条指令的偏移地址放在IP中,这样CPU就能指向我们定义的代码段中的指令。
对于栈段,将它的段地址放在SS中,将栈顶单元的偏移地址放在SP中,这样CPU在需要进行栈操作的时候,就将我们定义的栈段当作栈空间来操作。
比如我们将10000H - 1001FH 安排为代码段,并在里面存储如下代码:
mov ax, 1000H
mov ss, ax
mov sp, 0020H
mov ax, cs
mov ds, ax
mov ax, [0]
add ax, [2]
mov bx, [4]
add bx, [6]
push ax
push bx
pop ax
pop bx
设置CS = 10000H,IP=0。这段代码将得到执行,可以看到,在这段代码中,我们又将10000H - 1001FH 安排为栈段和数据段。10000H - 1001FH 这段内存,既是代码段,又是栈段和数据段。