速通汇编(六)认识栈,SS、SP寄存器,push和pop指令的作用

news2025/2/24 6:05:39

一,栈

(一)栈的特点

栈是一种具有特殊访问方式的存储空间,特殊在于,进出这块存储空间的数据,“先进后出,后进先出”

由于栈的这个“先进后出”的特点,我们可以利用其来很好的操作内存

在《王爽汇编》中,作者用三本书十分形象地来描述了入栈和出栈的操作,对栈比较陌生的同学可以仔细理解,很理解的同学则可跳过

入栈的方式

出栈的方式

入栈:将数据放在栈的顶部

出栈:将栈顶部的数据取出

也就是说,无论是入栈和出栈,当前操作的数据一定是当前栈中最顶部的数据,我们假想有一个指针,它会一直指着栈顶数据,帮助我们定位

(二)CPU中的栈机制

栈先进后出的这个特点对于我们操作数据是十分方便的一个机制,因此CPU中设计好了提供给我们相关的指令用这种机制来访问内存

简而言之,我们可以主观地将某块内存视作栈(实际上它在内存中是没变的,只是我们主观去刻意认为),然后用相关指令来操作它

最基本的两个入栈和出栈命令是:push(入栈),pop(出栈)

注意,入栈和出栈的操作都是以(一个字等于两个字节,1 word == 2 byte)为单位的,这意味着任何一次出入栈操作的数据一定是十六位的

例:

push ax        (√)

push bh        (×)bh是bx的高八位寄存器

pop cx          (√)

pop dl           (×)dl是dx的低八位寄存器

①初始空栈

规定为,如果将一块内存视作栈,那么这块内存最小的地址处(低地址)为栈顶,反之(高地址)为栈底,例如下图,[10000]为栈顶,[1000F]为栈底,你可以认为只不过是把从左到右(由低地址到高地址)的一块内存顺时针旋转了90度立起来方便我们看而已

此时栈指针指向[10010]处,即栈最底部[1000F]的再下一处,因为是空栈

下面将10000~1000F这段内存视作栈,并用相关指令来操作它

②【mov ax,0123】【push ax

将0123赋值给ax,然后把ax的值压入栈中

这里再次涉及到小端存储数据的方式(现有的机器基本都是小端存储),ax分为ah高位的01和al低位的23

因此高位的01应该放在[1000F]处,低位的23放在[1000E]处,因此执行完这两条汇编之后,栈中的数据应如下图所示

此时栈指针指向[1000E]处,栈顶数据是23

③【mov bx,2266】【push bx

这一步和②同理,高位的22被压入相对高位的[1000D]处,低位的66被压入相对低位的[1000C]处

此时栈指针指向[1000C]处,栈顶数据是66

 ④【mov cx,1122】【push cx

这一步和②③同理,高位的11被压入相对高位的[1000B]处,低位的22被压入相对低位的[1000A]处

此时栈指针指向[1000C]处,栈顶数据是22

(接下来3步我们整合在一起)

形如【pop 寄存器】指令的作用:将当前栈指针指向的数据放入寄存器中

⑤【pop ax】,栈指针指向[1000A]处,因此将66放入al,22放入ah(别忘了push和pop一定是以字为单位操作数据的,而不是字节),因此执行完后,ax==1122

⑥【pop bx】,同理,栈指针指向的是[1000C],将66放入bl,22放入bh,bx==2266

⑦【pop cx】,同理,栈指针指向的是[1000E],将23放入cl,01放入ch,cx==0123

最后,栈指针再次归位到[10010]处,因为栈空

总结:

①内存中地址从左到右由低到高,栈中地址从上到下由低到高,可以认为栈不过是一块内存顺时针旋转了90度立起来方便我们看而已

②假想一个栈指针,它会时刻指向栈中目前最顶部的数据

③push、pop指令操作的是至少是一个字(不能单独操作一个字节),一个字(word)==两个字节(byte)

④每使用push指令压入一个字,栈指针会向栈顶(低地址)处移动一个字的大小(相当于-2);每使用pop指令弹出一个字,栈指针会向栈底(高地址)处移动一个字的大小(相当于+2)


二,SS、SP寄存器和push、pop的作用

(一)SS、SP寄存器

在前文中,我们反复提到以下两点:

①栈是我们主观假想出来的具有特殊存储方式的内存,与普通内存别无二致

②假想一个栈指针,它会时刻指向栈中目前最顶部的数据

怎么让cpu知道我们把哪块内存视作栈了呢?这个假想出来的栈指针要如何表现呢?cpu提供给我们两个寄存器解决了这两个问题

回想一下,其实就像学习CS、IP寄存器时一样,我们当时解决的问题是“汇编指令和普通数据在内存中存储起来后没有差别(都是二进制数),但是cpu会将[CS:IP]指向的地址视作汇编来执行”;

所以现在举一反三,又需要两个这样的寄存器,一个用来标识段地址,一个用来标识偏移地址,它们共同指向我们主观视作栈的一块内存的栈顶数据,它的地址则是[SS:SP]

因此,[SS:SP]就是实际cpu中的栈指针

(二)push指令

 push指令主要有两种用法:

push 寄存器,例如:【push ax】

此处必须是十六位寄存器(前文已经阐述过)

当本条指令被执行之后,cpu会将指定寄存器ax的数据赋值给[SS:SP]处(即栈顶)

执行完后,SP寄存器的值会-2,因为新压入了两个字节的数据成为了新的栈顶数据,栈指针会向低地址偏移两个字节

push [偏移地址],例如:【push [0011]】

当本条指令被执行之后,cpu会将指定物理地址[DS:0011]处(不明白为什么是DS的,请仔细复习上一篇<速通汇编(五)>)的数据(同样是十六位数据,如FFFF)赋值给[SS:SP]处(即栈顶)

执行完后,SP寄存器的值会-2,因为新压入了两个字节的数据成为了新的栈顶数据,栈指针会向低地址偏移两个字节

实例:

①先用r命令查看寄存器,观察到SS和SP的值,然后用d命令查询[SS:SP]处内存的值

②在[0000:0000]处提前写入数据12ab34cd,修改DS的值为0000(这样待会push [0]时,[0]就代表[0000:0000])

④a命令在[CS:IP]即[073f:0100]处写入汇编

mov ax,1234】【push ax

push [0]

⑤执行前两条汇编【mov ax,1234】【push ax】,执行完后查看栈的变化

观察到,ax中的1234被压入栈中,ah的12在高地址,al的34在低地址,且SP==00FD-2==00FB,符合预期

(注:观察到此处栈顶数据左边的内存数据发生变化,这是正常现象,无需关心)

⑥执行第3条汇编【push [0]】,执行完后查看栈的变化

观察到,[0000:0000]处的两个字节12和AB,分别被压入栈的低和高地址处,且SP==00FB-2==00F9,符合预期

(三)pop指令

(pop指令用来弹出栈顶数据,弹出后不是说消失了,你要找个其它位置存放的)

pop指令主要有两种用法:

pop 寄存器,例如:【pop ax】

此处必须是十六位寄存器(前文已经阐述过)

当本条指令被执行之后,cpu会将[SS:SP]处(即栈顶)的数据弹出,赋值给指定寄存器ax

执行完后,SP寄存器的值会+2,因为弹出了栈顶数据,栈指针会向高地址处偏移2个字节

pop [偏移地址],例如:【pop [0011]】

当本条指令被执行之后,cpu会将[SS:SP]处(即栈顶)的数据弹出,赋值给指定物理地址[DS:0011]处

执行完后,SP寄存器的值会+2,因为弹出了栈顶数据,栈指针会向高地址处偏移2个字节

实例:

①a命令在在[CS:IP]处写入汇编

pop ax】【pop [0011]

②执行第一条汇编【pop ax】,执行完后查看栈与ax的变化

观察到,栈顶数据12AB被弹出,低位的12放入al中,高位的AB放入ah中,ax==AB12

且SP==00F9+2==00FB,符合预期

③执行第二条汇编【pop [0011]】,执行完后查看栈与[0000:0011]处的变化

观察到,栈顶数据3412被弹出,低位的34放入低位的[0000:0011]处,高位的12放入高位的[0000:0012]处

且SP==00FB+2==00FD,符合预期


三,栈越界相关问题

(以下是《王爽汇编》原文节选,提到的CPU通指8086CPU)

上文已经完全说明,CPU由SS和SP来指向栈顶地址,并提供push和pop指令来出入栈

有个问题是,CPU不会保证我们对栈的操作不超界

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2146944.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

传输层协议 —— TCP协议(上篇)

目录 1.认识TCP 2.TCP协议段格式 3.可靠性保证的机制 确认应答机制 超时重传机制 连接管理机制 三次握手 四次挥手 1.认识TCP 在网络通信模型中&#xff0c;传输层有两个经典的协议&#xff0c;分别是UDP协议和TCP协议。其中TCP协议全称为传输控制协议&#xff08;Tra…

Java毕业设计 基于SpringBoot和Vue自习室管理系统

Java毕业设计 基于SpringBoot和Vue自习室管理系统 这篇博文将介绍一个基于SpringBoot框架和Vue开发的自习室管理系统&#xff0c;适合用于Java毕业设计。 功能介绍 学生 登录 个人中心 修改密码 系统首页 自习室浏览 学生预约记录 管理员  登录 个人中心 修改密码 系统…

零信任安全架构--持续验证

随着网络安全威胁的不断演变&#xff0c;传统的“信任但验证”安全模式已无法应对现代复杂的攻击。零信任安全架构&#xff08;Zero Trust Architecture, ZTA&#xff09;应运而生&#xff0c;作为一种全新的安全理念&#xff0c;它彻底改变了企业的网络安全防护方式。核心思想…

file的判断和获取,创建和删除

常见成员方法 1.length 返回文件的大小(字节数量) 细节1:这个方法只能获取文件的大小&#xff0c;单位是字节如果单位我们要是M&#xff0c;G&#xff0c;可以不断的除以1024 细节2:这个方法无法获取文件夹的大小如果我们要获取一个文件夹的大小&#xff0c;需要把这个文件夹…

项目管理系统的期限提醒功能如何确保项目按时推进?

在竞争激烈的项目申报垂直领域&#xff0c;时间就是效率&#xff0c;效率关乎成败。每一个申报项目的截止日期都是一道不容错过的关卡&#xff0c;错过即意味着失去了宝贵的机会。为了确保项目能够按时推进&#xff0c;避免因时间管理不当而导致的延误&#xff0c;项目管理系统…

SpringCloud系列之一---搭建高可用的Eureka注册中心

前言 本篇文章主要介绍的是SpringCloud相关知识、微服务架构以及搭建服务注册与发现的服务模块(Eureka)以及Eureka集群。 GitHub源码链接位于文章底部。 什么是SpringCloud Spring Cloud 是一系列框架的有序集合。 它利用 Spring Boot 的开发便利性巧妙地简化了分布式系统基础设…

如何使用ssm实现基于web的物流配送管理系统的设计与实现+vue

TOC ssm646基于web的物流配送管理系统的设计与实现vue 第一章 绪论 1.1研究背景与意义 在科学技术水平还比较低下的时期&#xff0c;企业通常采用人工登记的方式对相关的物流配送信息进行记录&#xff0c;而后对这些信息记录进行管理和控制。这种采用纸质存储信息的管理模式…

平安养老险广东分公司:防范非法集资,守护消费者“钱袋子”

随着经济的不断发展&#xff0c;非法集资犯罪案件频频发生。非法集资案件受害人多&#xff0c;涉及资金广&#xff0c;犯罪手段多元化&#xff0c;涉案财物追缴困难等等。为提升金融消费者风险防范意识&#xff0c;保障其合法经济利益&#xff0c;今天我们一起来学习防范非法集…

利用条件编译解决vivado下verilog代码中ila与仿真的共存问题

vivado自带的仿真工具已经接近Modelsim的功能&#xff0c;且与原生开发环境的紧密结合&#xff0c;对仿真非常方便。 我的习惯是在实现工程中另外建一个仿真工程&#xff0c;保存仿真的testbench文件等&#xff0c;而实现工程中保存实际功能的源码文件。 这样仿真时会存在一个问…

PyQGIS开发 1 环境配置

PyQGIS 开发环境配置 1 安装QGIS QGIS官方下载地址 Windows环境下载对应版本的msi文件双击进行安装。 2 安装 PyCharm PyCharm官方下载地址 PyCharm官方提供专业版&#xff08;收费&#xff09;和社区版&#xff08;免费&#xff09;两个版本&#xff0c;自行选择下载、安…

Oracle EBS form个性化中调用带参数的存储过程或者函数

方式1 通过活动-消息 调用 这个方式的特点是会有一个消息弹框&#xff0c;不需要弹框时可以用方式2 方式2 通过 内置-执行过程 这个地方【变元】中的引用有点复杂&#xff0c;其中参数要用如下格式进行 #三个单引号||项目的表达式 ||${item.BLOCKNAME.FIELDNAME.value}|| #如…

从入门到精通,玩转Python的print函数(探索Python print函数的隐藏功能)

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 文章内容 📒📝 基础用法参数详解示例📝 高级用法自定义分隔符和结束符输出到文件追加模式📝 覆盖打印与进度条简单覆盖打印动态进度条示例代码⚓️ 相关链接 ⚓️📖 介绍 📖 刚开始学习编程时,我们接触到的第一个方…

运行npm install 时,卡在sill idealTree buildDeps没有反应

一直停留在sill idealTree buildDeps 解决方法 npm config set registry https://registry.npm.taobao.org 配置后用下面命令看是否配置成功 npm config get registry 如果配置还不好使 就执行下行的ssl npm set strict-ssl false 然后执行 npm install 成功执行

线程池的类型和状态

一、线程池的类型 1.通过Executors工具类创建的线程池对象 Executors.newFixedThreadPool(nThreads)&#xff1a;固定线程数目的线程池&#xff1b; 核心线程数和最大线程数一致&#xff1b;只要非核心线程空闲&#xff0c;则立刻被回收&#xff1b;工作队列为无界队列。 Exe…

基于yolov8的DMS驾驶员抽烟打电话喝水吃东西检测系统python源码+onnx模型+评估指标曲线+精美GUI界面

【算法介绍】 基于YOLOv8的DMS&#xff08;驾驶员监控系统&#xff09;驾驶员抽烟、打电话、喝水、吃东西检测系统是一种利用先进计算机视觉技术的实时监测系统。该系统通过YOLOv8算法&#xff0c;一种在速度和准确性上均表现优异的实时目标检测算法&#xff0c;实现对驾驶员行…

Spring Controller

服务器控制 响应架构 Spring Boot 内集成了 Tomcat 服务器&#xff0c;也可以外接 Tomcat 服务器。通过控制层接收浏览器的 URL 请求进行操作并返回数据。 底层和浏览器的信息交互仍旧由 servlet 完成&#xff0c;服务器整体架构如下&#xff1a; Server&#xff1a; Tomcat…

达梦数据库配置SSL通信加密

相关概念&#xff1a; SSL通过在发送方和接收方之间建立加密通道&#xff0c;确保数据在传输过程中的安全性和完整性。 SSL的关键特点 加密通信&#xff1a;SSL使用对称和非对称加密技术来加密数据&#xff0c;确保数据在传输过程中不被窃听或篡改。 身份验证&#xff1a;通…

若依VUE项目安全kind-of postcss vite漏洞扫描和修复

npm install unplugin-auto-import0.16.7 npm install vite3.2.11 升级vite、unplugin-auto-import npm install 报错New major version of npm available! 8.5.5 -> 10.8.3&#xff0c;使用命令npm install --force npm install --force

源代码防泄密的危害有哪些?担心源代码泄露?教你五种方法彻底阻止源代码泄密问题!

在数字经济蓬勃发展的今天&#xff0c;源代码&#xff0c;这个企业的核心技术资产&#xff0c;其安全性直接关系到企业的竞争力与生存。 一旦源代码泄露&#xff0c;不仅可能导致巨大的经济损失&#xff0c;更可能让企业陷入法律纠纷与声誉危机。 那么&#xff0c;源代码防泄密…

SOMEIP_ETS_117: SD_Entry_references_options_of_same_kind

测试目的&#xff1a; 验证DUT能够处理一个包含两种相同类型选项的SubscribeEventgroup消息&#xff0c;DUT可以选择拒绝订阅尝试或忽略该请求。 描述 本测试用例旨在确保DUT遵循SOME/IP协议&#xff0c;当接收到一个包含重复相同类型选项的SubscribeEventgroup消息时&#…