文章目录
- 前言
- 一、概念
- 二、栈
- 1.数据
- 入栈
- 出栈
- 2.指令
- push
- pop
- 3.设置
- 4.栈顶越界
- 5.栈的作用
- 主要作用
- 临时作用
前言
本文记录汇编语言中栈的概念和内容
一、概念
栈在汇编语言中,被定义为一段连续的内存单元
与数据结构类似,有数据入栈,出栈和栈顶的概念,但是在汇编语言中,我们可以直接接触到栈顶,也就是有相关标记表明栈顶的存在
二、栈
1.数据
在汇编语言中,入栈push和出栈pop可以对数据进行操作,这里进行操作的数据有如下的特征
- 数据从寄存器和内存中来
- 数据是字型数据,操作的是16位寄存器或内存中的字型数据
入栈
将16位寄存器或内存中的字型数据放到栈顶标记的上方
修改栈顶标记
出栈
将栈顶标记的字型数据 放到16位寄存器或内存中
修改栈顶标记
从上面我们可以看出,栈顶标记本质是一个内存地址,往栈(连续内存区域中)写入和拿出数据,都是针对相关内存地址进行修改;而在8086CPU中,在任意时刻,将段地址寄存器SS和偏移地址寄存器SP所组合出来的内存地址当作栈顶标记!
2.指令
push
push ax 所做的事情如下
修改SP寄存器中的数值:SP=SP-2
将AX中的字型数据->放到SS:SP所组合的内存地址中,入栈
pop
pop bx
将SS:SP所组合出的内存地址中的字型数据->bx
修改栈顶标记 SP=SP+2,出栈
3.设置
所谓栈所占据的空间,无非就是栈的起始地址和栈顶标记所在位置之间的距离
例如以下代码
mov ax,2000
mov ss,ax
mov ss,2000
mov sp,16
push ax
mov ax,2233
push ax
push ax
push ax
pop bx
pop cx
pop dx
这段代码便将栈的起始位置的段地址设置为2000,且将栈顶的偏移地址设置为16,这种情况下,栈中支持存储的字型数据为8个
通常,将栈设定位为16的倍数
4.栈顶越界
当push入栈数据大小或者pop出栈数据大小大于栈顶标记与栈的起始地址所组成的栈空间时,便会发生栈顶越界问题,但汇编语言并不会像其他高级语言那样直接抛出异常和错误
汇编语言在任意时刻,都会将ss:sp所组成的地址认为为栈顶标记
例如以下情况
在这段代码中,可以清楚地看到sp寄存器中的数值减到0后会跳转至FFFE,而这段存储空间所存储的指令或数据我们不得而知,也就是说,在汇编语言中,虽然栈顶越界不会带来直接的异常错误,但如果我们通过push或者pop破坏我们原已有的指令或者数据,也是十分致命的
从以上我们可以看到,SP寄存器的变化范围为0~FFFFH,也就是65536个字节,32768个字型数据,也就是我们原来所说的64KB
5.栈的作用
主要作用
栈的主要作用:临时性地保存数据
在call指令和ret指令中,call转移指令临时地将吓一跳指令所在的地址保存了栈中栈顶位置,再通过ret指令从栈顶将保存的指令拿出
临时作用
- 用于数据交换
例:
mov ax,1122
mov bx,3344
push ax
push bx
pop ax
pop bx
mov ax,1000H
mov ds,ax
push ds:[0]
push ds:[2]
pop ds:[0]
pop ds:[2]