汇编:栈

本文最后更新于:2022年11月8日 上午

栈是一种常用的数据结构,具有先进后出的特点FILO(First In Last out)

汇编中栈的使用

栈是一种常用的数据结构,具有先进后出的特点FILO(First In Last out),汇编中也有栈的概念,通过PUSHPOP 来操作栈

例如 push ax 表示将ax的值存到栈顶中,pop bx表示将栈顶数据取出并给bx赋值。在8086CPU中,通过SS段寄存器SP寄存器来记录栈顶的位置(猜测SS和SP 寄存器的开头的S表示的是Stack)

PUSH指令

POP指令

这里需要注意pop指令,pop指令之前我们知道pop bx表示将栈顶数据取出并给bx赋值,此时栈中其实还是保留原有的数据的,只是SP寄存器的偏移量向前+2了,下一次push的时候才会把数据覆盖掉

栈越界的情况

当我们将一块区域视为栈空间后,SSSP 永远只会指向当前栈顶的位置,在8086CPU中,它没有单独的寄存器来记录栈顶上限和栈底。所以在8086CPU要自己操心栈顶越界的情况

push 导致栈越界

pop导致栈越界

PUSH, POP 在汇编中的具体使用

在汇编中,栈空间也是内存的空间的一部分,他只是可以通过一种特殊的方式进行访问的内存空间。主要就是通过pushpop来对栈空间进行操作

在对栈空间进行操作是,pushpop有以下几种用法

栈空间的操作是以字为单位的,也就是一个8086CPU中一个寄存器的容量,也是一个字(两个字节,两个8位),所以以下的操作都是以字为单位的,可以注意看下

push 寄存器

push 段寄存器

push 内存单元

------------

pop 寄存器

pop 段寄存器

pop 内存单元

比如
mov ax, 1000H
mov ds, ax     // 将段地址设置为 1000H
push [0]       // 将 1000:0000 的处的字压入到栈中
pop [2]        // 出栈,将出栈的数据送入到 1000:0002 的位置

示例

  1. 10000H - 1000FH 这段空间当做栈,初始状态是空的
  2. 设置 ax=001AH, bx=001BH
  3. ax,bx添加到栈中
  4. ax,bx清零(值变成0)
  5. 从栈中恢复ax,bx的数据
mov ax, 1000H
mov ss, ax
mov sp, 00010;

mov ax, 001A;
mov bx, 001B;

push ax;
push bx;

sub ax, ax; // 自己减去自己,也可以用 mov ax, 0;  sub ax, ax 的机器码为2个字节, mov ax, 0 的字节码是3个字节
sub bx, bx;

pop bx;     // 先从栈顶取出内容
pop ax;

注意栈顶的位置,因为每次往栈中添加数据SP是做减的操作的,所以初始化时栈顶会设置在栈区域的最高位置。例如 push ax; sp -=2;

测试1

如果要在10000H中写入字型数据2266H,可以用以下方式

mov ax, 10000H
mov ds, ax
mov [0], 2266H

现在要求不能 mov 寄存器, 内存单元的方式来编写,换成以下方式

mox ax, 1000
mov ss, ax
mov sp, 2;    // 这里需要注意先将sp=sp+2, 才能保证写入的时候写入的是1000H的位置
mov ax, 2266;
push ax;

push和pop的具体操作

pushpop执行的操作和mov不一样,mov指令CPU只需要执行一步操作,就是传送。而pushpop需要两步。

push

1,先改变sp
2,再向ss:sp的位置传送

pop

1, 先从ss:sp的位置取出数据
2,再改变sp

pushpop的操作都是在修改spsp是一个16位的寄存器,也就是说栈顶的变化范围最大是 0-FFFFH


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议,转载请注明出处。