堆栈

堆栈 :“先进后出”的存储区,存在于堆栈段中,SP在任何时候都指向栈顶。

一、PUSH指令(字入栈)

1、格式:PUSH 源操作数(字)

1
PUSH    AX   ;AX进栈

2、功能
(1)首先将栈顶 指针 减2,即(SP)-2=>SP;
(2)然后将源操作数(字)=>((SP)+1,(SP))。(高字节,低字节)
即执行操作:

  • (SP)<– (SP)-2
  • ((SP)+1,(SP)) <– (源操作数)

3、说明
高字节先进栈,低字节在栈顶
图片.png


PUSHAD指令

图片.png

在实际应用中,pushad 和 popad 常用于函数调用或中断处理程序的开头和结尾,以此来保存和恢复寄存器状态,确保这些操作不会对调用者的寄存器值产生影响。不过要留意,这两条指令会对栈进行大量操作,所以在栈空间有限的情形下要谨慎使用。

二、POP指令(字出栈)

1、格式:POP 目的操作数

1
POP AX   ;恢复AX

2、功能
(1)首先将栈顶的字((SP)+1,(SP))=>目的操作数;
(2)然后将堆栈指针SP加2,即(SP)+2=>SP。
即执行操作:

  • (DST)<– ((SP)+1,(SP))
  • (SP) <– (SP)+2

图片.png


三、堆栈操作说明

1、栈顶SP指向数据
 因为堆栈指针SP总是指向已经存入数据的栈顶(不是空单元),所以PUSH指令时先将(SP)减2,后将内容压栈(即先修改SP使之指向空单元,后压入数),而POP是先从栈顶弹出一个字,后将堆栈指针SP加2.
2、对代码段寄存器
 PUSH CS是合法的,但POP CS是不合法的。
3、堆栈特点—–FILO
 因为SP总是指向栈顶,而用PUSH和POP指令存取数时都是在栈顶进行的,所以堆栈是“先进后出”或叫“后进先出”的。栈底在高地址,堆栈是从高地址向低地址延伸的,所以栈底就是最初的栈顶。
4、按字访问
 用PUSH指令和POP指令时只能按字访问堆栈,不能按字节访问堆栈。
5、不影响标志
 PUSH和POP都不影响标志。
6、不能用立即寻址方式
PUSH 1234H ;错误!!


小例子:

这里就是对AX清零。

1
2
3
4
5
6
PUSH    DS
SUB AX,AX
PUSH AX
...
...
RET

下面就是一个保护现场的代码

1
2
3
4
5
6
7
PUSH    AX
PUSH BX
PUSH CX
......;期间用到了AX、BX、CX
POP CX
POP BX
POP AX

从键盘上键入10个字符,然后与键入字符的先后相反的顺序显示出来。( 使用 堆栈的办法)
分析:因为堆栈是“后进先出”的,因此,利用堆栈作为输出缓冲区极易实现按逆序输出。
 分配一个256个字的堆栈缓冲区,在其低字节中存放从键盘上键入的字符。我们将从键盘上接受来的10个字符依次进栈,存放在这片堆栈区里,然后再从最后一个字单元开始,弹出堆栈,即可逆序把它们显示出来。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
STACKS SEGMENT PARA STACK 'STACK'
DW 256 DUP(?) ;堆栈只能是一个字一个字的操作,多预留点栈空间
STACKS ENDS

CODES SEGMENT
ASSUME CS:CODES,SS:STACKS
START:
MOV AX,STACKS ;这里就用STACKS,以前都是DATAS
MOV SS,AX ;这里就用SS了,以前都是用DS
MOV CX,10 ;输入10个字符=>堆栈
READ:
MOV AH,01H
INT 21H
PUSH AX ;堆栈操作都是‘字’,不能用AL,浪费了AH的空间
LOOP READ ;读10个字符

MOV DL,0AH ;显示回车
MOV AH,02H
INT 21H
MOV DL,0DH ;显示换行
INT 21H

MOV CX,10 ;从栈顶依次弹出10个字符输出
DISP:
POP DX ;显示
MOV AH,02H
INT 21H
LOOP DISP ;显示10个字符

MOV AH,4CH
INT 21H
CODES ENDS
END START

四、堆栈操作说明

(1)堆栈指针SP的自动赋值
 只要在堆栈段的SEGMENT伪指令中带有组合 类 型参数和组名参数:STACK ‘STACK’,汇编程序就会自动把栈底(也是最初的栈顶)的位移量赋给堆栈指针SP。
(2)空间有浪费
 因堆栈只对字操作,故10个字符的高字节虽然入了栈,但未用,浪费了一半空间。
(3)堆栈大小留有余地
 虽然只输入10个字符,但堆栈 定义 了256个字(100H)。一般定义时适当留有余地。