堆栈

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

PUSH指令(字入栈)

格式:PUSH 源操作数(字)

PUSH AX   ;AX进栈

PUSH 指令首先减少 ESP 的值,再将源操作数复制到堆栈。操作数是 16 位的,则 ESP 减 2,操作数是 32 位的,则 ESP 减 4。PUSH 指令有 3 种格式:

PUSH reg/mem16  
PUSH reg/mem32  
PUSH imm32

注意:push指令不允许8位寄存器

高字节先进栈,低字节在栈顶
图片.png


PUSHAD指令

图片.png

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

POP指令(字出栈)

格式:POP 目的操作数

POP AX   ;恢复AX

图片.png POP 指令首先将当前栈顶(ESP所指向的内存单元)的数据复制到目的操作数中,然后再增加 ESP 的值(因为出栈意味着栈顶指针向高地址回退)。如果操作数是 16 位的,则 ESP 加 2;如果操作数是 32 位的,则 ESP 加 4。

POP 指令主要有以下 2 种格式(注意:目的操作数不能是立即数):

1 POP reg/mem16   ;弹出到 16 位寄存器或内存单元
2 POP reg/mem32   ;弹出到 32 位寄存器或内存单元

注意:

  1. 与 PUSH 相同,POP 指令不允许使用 8 位寄存器(如 AL, AH 等)。
  2. 目的操作数不能是立即数(你不能把栈里的数据弹到一个固定常数里)。
  3. POP CS 是非法的(代码段寄存器 CS 不能通过 POP 指令直接修改,这会在你下方的“堆栈操作说明”中提到)。

POPAD指令

堆栈操作说明

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清零。

PUSH    DS
SUB AX,AX
PUSH    AX
...
...
RET

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

PUSH    AX
PUSH    BX
PUSH    CX
......;期间用到了AX、BX、CX
POP CX
POP BX
POP AX

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

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)。一般定义时适当留有余地。

函数调用

绘制堆栈图

步骤一:在动调中用F3快捷键打开HelloWorld.exe程序 步骤二:Ctrl+G快捷键弹出窗口,在窗口中输入地址