3.8 栈顶越界的问题
push越界,上溢出;pop越界,下溢出
栈空间之前的空间里很可能存放了具有其他用途的数据、代码
- 我们在编程时要自己操心栈顶越界的问题,要根据可能用到的最大栈空间,来安排栈的大小,防止入栈的数据太多而导致越界
- 执行出栈的操作时也要注意,以防止栈空的时候继续出栈而导致的越界
3.9 push、pop指令
push和pop指令是可以在寄存器和内存之间传送数据的。
栈空间当然也是内存空间的一部分,它只是一段可以以一种特殊方式进行访问的内存空间
push和pop指令的格式
一:
- push 寄存器:将一个寄存器中的数据入栈
- pop 寄存器:用一个寄存器接受出栈的数据
二:
- push 段寄存器:将一个段寄存器中的内容入栈
- pop 段寄存器:用一个段寄存器接受出栈的数据
三:
push 内存单元:将一个内存单元处的字入栈(栈操作都是以字为单位)
pop 内存单元:用一个内存单元来接收出栈的数据
push [0]
、pop [2]
指令执行时,CPU要知道内存单元的地址,可以在push、pop指令中给出内存单元的偏移地址,段地址在指令执行时,CPU从ds中取得。
问题:3.7
将10000H~1000FH这段空间当做栈,初始状态是空的,将AX、BX、DS中的数据入栈。
1
2
3
4
5
6
7 mov ax 1000H
mov ss, ax ; 设置栈的段地址,SS=1000H,不能直接向段寄存器SS送入数据
mov sp, 0010H ; 栈为空时,ss:sp在1000FH的下一位
push ax
push bx
push ds
问题:3.8
编程:
- 将10000H~1000FH 这段空间当作栈,初始状态是空的;
- 设置AX=001AH,BX=001BH;
- 将AX、BX中的数据入栈;
- 然后将AX、BX清零;
- 从栈中恢复AX、BX原来的内容。
类似于函数调用过程:main函数调用a函数,初始时先将main函数的寄存器入栈,进行完操作后恢复寄存器到初始状态,回到main函数执行下面的内容
1
2
3
4
5
6
7
8
9
10
11 mov ax, 1000H
mov ss, ax
mov sp, 1010H ;初始化栈顶
mov ax, 001AH
mov bx, 001BH
sub ax, ax ;将ax清零,也可以用赋值:mov ax, 0 异或: xor ax, ax
sub bx, bx ;sub ax,ax的机器码为2个字节
;mov ax,0 的机器码为3个字节
pop bx ;从栈中恢复ax,bx原来的数据,当前栈顶的内容是bx
pop ax ;中原来的内容
问题3.9
编程:
- 将10000H~1000FH这段空间当作栈,初始状态是空的
- 设置AX=002AH,BX=002BH
- 利用栈,交换AX和BX中的数据
1
2
3
4
5
6
7
8
9 mov ax, 1000H
mov ss, ax
mov sp, 1010H
mov ax, 002AH
mov bx, 002BH
push ax
push bx
pop ax
pop bx
问题3.10
我们如果要在10000H处写入字型数据2266H,可以用以下的代码完成:
1
2
3
4 mov ax, 1000H
mov ds, ax
mov ax, 2266H
mov [0], ax换一个写法:要求写入字型数据2266H
1
2
3
4
5 ______
______
______
mov ax, 2266H
push ax不能使用
mov 内存单元, 寄存器
这类指令答:
1
2
3 mov ax, 1000H
mov ss, ax
mov sp, 2 ; push 会让 sp = sp - 2
执行push、pop指令需要两步:
- 执行push时
- 先改变sp,后向SS:SP处传送
- SP=SP-2
- 向SS:SP指向的字单元中送入数据
- 先改变sp,后向SS:SP处传送
- 执行pop时
- 先读取SS:SP处的数据,后改变SP。
- 向SS:SP指向的字单元中读取数据
- SP=SP+2
- 先读取SS:SP处的数据,后改变SP。
push、pop等栈操作指令,修改的只是SP。也就是说,栈顶的变化范围最大为:0~FFFFH。
综述:
- 任意时刻,SS:SP指向栈顶元素
- 8086CPU只记录栈顶,栈空间的大小我们要自己管理