找回密码
 register

QQ登录

只需一步,快速开始

查看: 28|回复: 0

[汇编语言] [零基础入门学习]·15·寄存器(内存访问)·栈顶超界的问题·push、pop指令

[复制链接]

[汇编语言] [零基础入门学习]·15·寄存器(内存访问)·栈顶超界的问题·push、pop指令

[复制链接]
  • 打卡等级:热心大叔
  • 打卡总天数:91
  • 打卡月天数:14
  • 打卡总奖励:91
  • 最近打卡:2025-01-15 02:59:34
Waylee

主题

0

回帖

1万

积分

仙帝

积分
11890
Waylee 2024-12-28 16:51 | 显示全部楼层 |阅读模式 | Google Chrome | Windows 10

马上注册,查看网站隐藏内容!!

您需要 登录 才可以下载或查看,没有账号?register

×


3.8 栈顶超界的问题

我们现在知道,8086CPU用SS和SP指示栈顶的地址,并提供push和pop指令实现入栈和出栈。

但是,还有一个问题需要讨论,就是SS和SP只是记录了栈顶的地址,依靠SS和SP可以保证在入栈和出栈时找到栈顶。可是,如何能保证在入栈、出栈时,栈顶不会超出栈空间?

图3.13描述了在执行push指令后,栈顶超出栈空间的情况。

图3.13中,将10010H~1001FH当作栈空间,该栈空间容量为16字节(8字),初始状态为空,SS=1000H、SP=0020H,SS:SP指向10020H;

在执行8次push ax后,向栈中压入8个字,栈满,SS:SP指向10010H;

再次执行push ax:sp=sp-2,SS:SP指向1000EH,栈顶超出了栈空间,ax中的数据送入1000EH单元处,将栈空间外的数据覆盖。

001.webp

图3.14描述了在执行pop指令后,栈顶超出栈空间的情况。

图3.14中,将10010H~1001FH当作栈空间,该栈空间容量为16字节(8字),当前状态为满,SS=1000H、SP=0010H,SS:SP指向10010H;

002.webp

在执行8次pop ax后,从栈中弹出8个字,栈空,SS:SP指向10020H;

再次执行pop ax:sp=sp+2,SS:SP指向10022H,栈顶超出了栈空间。此后,如果再执行push指令,10020H、10021H中的数据将被覆盖。

上面描述了执行push、pop指令时,发生的栈顶超界问题。可以看到,当栈满的时候再使用push指令入栈,或栈空的时候再使用pop指令出栈,都将发生栈顶超界问题。

栈顶超界是危险的,因为我们既然将一段空间安排为栈,那么在栈空间之外的空间里很可能存放着具有其他用途的数据、代码等,这些数据、代码可能是我们程序中的,也可能是别的程序中的(毕竟一个计算机系统中并不是只有我们自己的程序在运行)。但是由于我们在入栈出栈时的不小心,而将这些数据、代码意外地改写,将会引发一连串的错误。

我们当然希望CPU可以帮我们解决这个问题,比如说在CPU中有记录栈顶上限和栈底的寄存器,我们可以通过填写这些寄存器来指定栈空间的范围,然后CPU在执行push指令的时候靠检测栈顶上限寄存器、在执行pop指令的时候靠检测栈底寄存器保证不会超界。

不过,对于8086CPU,这只是我们的一个设想(我们当然可以这样设想,如果CPU是我们设计的话,这也就不仅仅是一个设想)。实际的情况是,8086CPU中并没有这样的寄存器。

8086CPU不保证我们对栈的操作不会超界。这也就是说,8086CPU只知道栈顶在何处(由SS:SP指示),而不知道我们安排的栈空间有多大。这点就像CPU只知道当前要执行的指令在何处(由CS:IP指示),而不知道要执行的指令有多少。从这两点上我们可以看出8086CPU的工作机理,它只考虑当前情况:当前的栈顶在何处、当前要执行的指令是哪一条。

我们在编程的时候要自己操心栈顶超界的问题,要根据可能用到的最大栈空间,来安排栈的大小,防止入栈的数据太多而导致超界;执行出栈操作的时候也要注意,以防栈空的时候继续出栈而导致的超界。

3.9 push、pop指令

前面我们一直在使用push ax和pop ax,显然push和pop指令是可以在寄存器和内存(栈空间当然也是内存空间的一部分,它只是一段可以以特殊的方式进行访问的内存空间。)之间传送数据的。

push和pop指令的格式可以是如下形式:

push 寄存器    ;将一个寄存器中的数据入栈
pop 寄存器     ;出栈,用一个寄存器接收出栈的数据

当然也可以是如下形式:

push 段寄存器   ;将一个段寄存器中的数据入栈
pop 段寄存器    ;出栈,用一个段寄存器接收出栈的数据

push和pop也可以在内存单元和内存单元之间传送数据,我们可以:

push 内存单元   ;将一个内存字单元处的字入栈(注意:栈操作都是以字为单位)
pop 内存单元    ;出栈,用一个内存字单元接收出栈的数据

比如

mov ax,1000H
mov ds,ax       ;内存单元的段地址要放在ds中
push [0]        ;将1000:0处的字压入栈中
pop [2]         ;出栈,出栈的数据送入1000:2处
您需要登录后才可以回帖 登录 | register

本版积分规则

雪舞知识库 | 浙ICP备15015590号-1 | 萌ICP备20232229号|浙公网安备33048102000118号 |天天打卡

GMT+8, 2025-1-15 17:14 , Processed in 0.111051 second(s), 8 queries , Redis On.

Powered by XueWu Licensed

Copyright © Tencent Cloud.

快速回复 返回顶部 返回列表