【汇编语言】栈区与SS:SP寄存器

汇编语言 - 栈

栈是一块特殊的内存空间,本文涉及的CPU为8086CPU,所有与内存地址有关的数字皆为16进制

前言

栈的运行规律 - 先进后出,后进先出

以下为入栈的过程:
image-20210925114650198

以下是出栈的过程:

image-20210925115129316

以上就是栈的运行机制,栈的入栈叫做push,出栈叫做pop

在8086CPU中,栈是一块特殊的内存空间,栈的出栈和入栈都是以字为单位的

1. 8086栈机制

8086使用一段内存对栈进行模拟,最基本的操作是pop(出栈)和push(入栈)

  • pop 寄存器 : 表示将栈顶元素出栈并且将数据送入寄存器中
  • push 寄存器: 表示将寄存器中的元素入栈

下面是一段当作栈区使用的内存空间,初始化如下:

image-20210808175019996

执行指令:push AX后:

bandicam 2021-08-08 17-54-31-035

寄存器AX中的内容被存放进内存中,栈顶指针上移两个字节

执行指令 push BX 后:

bandicam 2021-08-08 17-55-37-204

寄存器BX中的内容被存放进内存中,栈顶指针上移两个字节

执行指令pop CX中:

bandicam 2021-08-08 17-56-16-841

将栈顶元素送入CX后,栈顶指针下移两个字节

我们只需要使用pop和push指令,就可以对这段内存空间按照先进先出的规则进行访问,那么CPU怎么知道这段空间就是栈空间呢?

2. SS和SP寄存器

CPU是怎么知道我们执行的指令的地址?CPU是怎么知道我们执行指令的时候需要的数据的地址的?CPU通过CS:IP寄存器确定指令的位置,CPU通过DS:[address]确认数据的位置,那么需要确定栈顶的位置,也需要添加寄存器,SS与SP寄存器就是用来确定栈顶的位置的。

SS寄存器中存着栈顶的段地址,SP寄存器中存放着偏移地址,通过这两个寄存器中的值就可以判断栈顶的位置。

2.1 push指令与pop指令

push指令的完成,需要以下两个步骤

  1. SP = SP - 2:因为SS:SP指向前栈顶,既然需要push 数据,自然需要获取新栈顶
  2. 将 push 后面跟的寄存器中的内容写入刚开辟出的内存中,此时的SS:SP指向新栈顶

入栈时,栈顶从高地址向低地址增长

pop指令的完成,需要以下两个步骤

  1. 将栈顶元素送入pop后面跟的寄存器中
  2. SP = SP + 2,SS:SP指向下一个元素

出栈时,栈顶从低地址向高地址增长

2.2 示例

测试初始空间如下:

图中的栈顶SS:IP应为 SS:SP

bandicam 2021-08-08 18-24-07-278

当前SS:SP指向1000:A

执行push AX 指令后:

栈顶指针先上移,SP = SP - 2,然后将AX中的数据写入栈顶

在这里插入图片描述

执行push BX指令后:

栈顶指针先上移,SP = SP - 2,然后将BX中的数据写入栈顶

执行pop AX指令后:

先将栈顶中的数据写入AX中,然后栈顶指针下移,SP=SP + 2

bandicam 2021-08-08 18-33-36-806

执行pop BX指令后:
先将栈顶的数据写入BX中,然后栈顶指针下移,SP = SP + 2

bandicam 2021-08-08 18-34-22-649

如果1000:0 到 1000:F 这块内存是栈空间,并且初始状态栈空,那么初始状态下栈顶指针应指向1001:0,也就是第一次PUSH时栈顶指针刚好能够减到1000:E

image-20210808185340054

2.3 越界问题

因为8086CPU只提供了栈顶寄存器,如果划分了一段内存空间为栈空间,例如1000:0 到 1000:F,如果SS:SP指针通过一系列的push和pop操作超出了这个范围,出现了上溢或者下溢的问题,是没有办法解决的,因为8086CPU 并没有提供对应的寄存器存放栈空间的大小,不能在每次push和pop操作之前先判断是否越界。

只能通过自己编程的时候避免。

3. debug测试

3.1 例题

利用栈的功能交换两个寄存器中的内容

寄存器和内存初始化

bandicam 2021-08-08 22-08-42-419

将AX压栈:

bandicam 2021-08-08 22-11-26-181

将BX压栈:

bandicam 2021-08-08 22-11-58-275

将栈顶pop到AX中:

bandicam 2021-08-08 22-12-51-622

将栈顶pop到BX中

bandicam 2021-08-08 22-13-31-571

完成两个寄存器中的内容交换

3.2 在debug中进行测试

  1. 先将AX和BX中的内容设置为1234H和5678H,然后找好栈区
image-20210808222026677
  1. 写入对应的代码
image-20210808222200427
  1. 将CS:IP指向对应的代码处,则开始运行程序
image-20210808222440961

执行完代码后成功交换寄存器中的值

猜你喜欢

转载自blog.csdn.net/qq_45978890/article/details/119522352
今日推荐