堆栈
堆栈
堆栈 :“先进后出”的存储区,存在于堆栈段中,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、说明
高字节先进栈,低字节在栈顶
PUSHAD指令
在实际应用中,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
三、堆栈操作说明
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 | PUSH DS |
下面就是一个保护现场的代码
1 | PUSH AX |
从键盘上键入10个字符,然后与键入字符的先后相反的顺序显示出来。( 使用 堆栈的办法)
分析:因为堆栈是“后进先出”的,因此,利用堆栈作为输出缓冲区极易实现按逆序输出。
分配一个256个字的堆栈缓冲区,在其低字节中存放从键盘上键入的字符。我们将从键盘上接受来的10个字符依次进栈,存放在这片堆栈区里,然后再从最后一个字单元开始,弹出堆栈,即可逆序把它们显示出来。
1 | STACKS SEGMENT PARA STACK 'STACK' |
四、堆栈操作说明
(1)堆栈指针SP的自动赋值
只要在堆栈段的SEGMENT伪指令中带有组合 类 型参数和组名参数:STACK ‘STACK’,汇编程序就会自动把栈底(也是最初的栈顶)的位移量赋给堆栈指针SP。
(2)空间有浪费
因堆栈只对字操作,故10个字符的高字节虽然入了栈,但未用,浪费了一半空间。
(3)堆栈大小留有余地
虽然只输入10个字符,但堆栈 定义 了256个字(100H)。一般定义时适当留有余地。





