0%

汇编语言学习笔记(七)

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

截屏2021-06-26 下午3.26.03

执行push、pop指令需要两步:

  • 执行push时
    • 先改变sp,后向SS:SP处传送
      • SP=SP-2
      • 向SS:SP指向的字单元中送入数据
  • 执行pop时
    • 先读取SS:SP处的数据,后改变SP。
      • 向SS:SP指向的字单元中读取数据
      • SP=SP+2

push、pop等栈操作指令,修改的只是SP。也就是说,栈顶的变化范围最大为:0~FFFFH。

综述:

  • 任意时刻,SS:SP指向栈顶元素
  • 8086CPU只记录栈顶,栈空间的大小我们要自己管理