【汇编语言】call 和 ret 指令(三) —— 深度解析汇编语言中的批量数据传递与寄存器冲突
文章目录
- 前言
- 1. 批量数据的传递
- 1.1 存在的问题
- 1.2 如何解决这个问题
- 1.3 示例演示
- 1.3.1 问题说明
- 1.3.2 程序实现
- 2. 寄存器冲突问题的引入
- 2.1 问题引入
- 2.2 分析与解决问题
- 2.2.1 字符串定义方式
- 2.2.2 分析子程序功能
- 2.2.3 得到子程序代码
- 2.3 子程序的应用
- 2.3.1 示例1
- 2.3.2 示例2
- 3. 寄存器冲突问题的发现与解决
- 3.1 重看代码
- 3.2 分析与解决问题
- 3.2.1 存在的冲突问题
- 3.2.2 解决方案的探讨
- 3.2.3 给出解决方案。
- 3.2.4 子程序的标准框架
- 3.2.5 改进之前的程序
- 结语
前言
📌
汇编语言是很多相关课程(如数据结构、操作系统、微机原理)的重要基础。但仅仅从课程的角度出发就太片面了,其实学习汇编语言可以深入理解计算机底层工作原理,提升代码效率,尤其在嵌入式系统和性能优化方面有重要作用。此外,它在逆向工程和安全领域不可或缺,帮助分析软件运行机制并增强漏洞修复能力。
本专栏的汇编语言学习章节主要是依据王爽老师的《汇编语言》来写的,和书中一样为了使学习的过程容易展开,我们采用以8086CPU为中央处理器的PC机来进行学习。
1. 批量数据的传递
1.1 存在的问题
前面学习的例程中,子程序 cube 只有一个参数,放在bx中。如果有两个参数,那么可以用两个寄存器来放,可是如果需要传递的数据有3个、4个或更多直至 N个,我们怎样存放呢?
寄存器的数量终究有限,我们不可能简单地用寄存器来存放多个需要传递的数据。对于返回值,也有同样的问题。
1.2 如何解决这个问题
在这种时候,我们将批量数据放到内存中,然后将它们所在内存空间的首地址放在寄存器中,传递给需要的子程序。对于具有批量数据的返回结果,也可用同样的方法。
接下来我们来看下具体的落实……
1.3 示例演示
1.3.1 问题说明
下面看一个例子,
设计一个子程序,功能:将一个全是字母的字符串转化为大写。
这个子程序需要知道两件事,字符串的内容和字符串的长度。
因为字符串中的字母可能很多,所以不便将整个字符串中的所有字母都直接传递给子程序。但是,可以将字符串在内存中的首地址放在寄存器中传递给子程序。因为子程序中要用到循环,我们可以用loop指令,而循环的次数恰恰就是字符串的长度。
出于方便的考虑,可以将字符串的长度放到cx。
capital: and byte ptr [si],11011111b ;将ds:si所指单元中的字母转化为大写inc si ;ds:si 指向下一个单元loop capital ret
1.3.2 程序实现
编程:将data段中的字符串转化为大写。
assume cs:codedata segmentdb 'conversation'
data endscode segmentstart: mov ax,datamov ds,axmov si,0 ;ds:si指向字符串(批量数据)所在空间的首地址mov cx,12 ;cx存放字符串的长度call capitalmov ax,4c00hint 21hcapital:and byte ptr [si],11011111binc siloop capitalretcode endsend start
❗注意:除了寄存器、内存传递参数外,还有一种通用的方法使用栈来传递参数。
2. 寄存器冲突问题的引入
2.1 问题引入
设计一个子程序:功能:将一个全是字母,以0结尾的字符串,转化为大写。
2.2 分析与解决问题
2.2.1 字符串定义方式
程序要处理的字符串以0作为结尾符,这个字符串可以如下定义:
db ‘conversation’,0
2.2.2 分析子程序功能
应用这个子程序 ,字符串的内容后面定要有一个0,标记字符串的结束。
子程序可以依次读取每个字符进行检测,如果不是0,就进行大写的转化,如果是0,就结束处理。
由于可通过检测0而知道是否己经处理完整个字符串 ,所以子程序可以不需要字符串的长度作为参数。
我们可以直接用jcxz来检测0。
2.2.3 得到子程序代码
;说明:将一个全是字母,以0结尾的字符串,转化为大写
;参数:ds:si指向字符串的首地址
;结果:没有返回值
capital:mov cl,[si]mov ch, 0jcxz ok ;如果(cx)=0,结束;如果不是0,处理and byte ptr [si], 11011111b ;将ds:si所指单元中的字母转化为大写inc si ;ds:si 指向下一个单元jmp short capitalok:ret
2.3 子程序的应用
来看一下这个子程序的应用。
2.3.1 示例1
要求:将data段中的字符串转化为大写。
assume cs:code
data segmentdb 'conversation',0
data ends
代码段中的相关程序如下。
mov ax,data
mov ds,ax
mov si,0
call capital
2.3.2 示例2
要求:将data段中字符串全部转化为大写。
assume cs:codedata segmentdb 'word', 0db 'unix', 0db 'wind', 0db 'good', 0
data ends
可以看到,所有字符串的长度都是5(算上结尾符0),使用循环,重复调用子程序capital,完成对4个字符串的处理。
完整的程序如下。
code segment
start: mov ax,datamov ds,axmov bx,0mov cx,4s: mov si,bxcall capitaladd bx,5loop smov ax,4c00hint 21hcapital:mov cl,[si]mov ch, 0jcxz okand byte ptr [si], 11011111binc sijmp short capitalok:retcode endsend start
3. 寄存器冲突问题的发现与解决
3.1 重看代码
上面的这个程序在思想上完全正确,但在细节上却有些错误,把错误找出来。
提示:问题在于cx的使用。
思考后看分析。
3.2 分析与解决问题
3.2.1 存在的冲突问题
问题在于cx的使用,主程序要使用cx记录循环次数,可是子程序中也使用了cx,在执行子程序的时候,cx中保存的循环计数值被改变,使得主程序的循环出错。
从上面的问题中,实际上引出了一个一般化的问题:子程序中使用的寄存器,很可能在主程序中也要使用,造成了寄存器使用上的冲突。
3.2.2 解决方案的探讨
那么如何来避免这种冲突呢?
粗略地看,可以有以下两个方案。
(1)在编写调用子程序的程序时,注意看看子程序中有没有用到会产生冲突的寄存器,如果有,调用者使用别的寄存器;
(2)在编写子程序的时候,不要使用会产生冲突的寄存器。
我们来分析一下上面两个方案的可行性:
(1)这将给调用子程序的程序的编写造成很大的麻烦,因为必须要小心检查所调用的子程序中是否有将产生冲突的寄存器。
比如说,在上面的例子中,我们在编写主程序的循环的时候就得检查子程序中是否用到了bx和cx,因为如果子程序中用到了这两个寄存器就会出现问题。
如果采用这种方案来解决冲突的话,那么在主程序的循环中,就不能使用cx寄存器,因为子程序中已经用到。
(2)这个方案也是不可能实现的,因为编写子程序的时候无法知道将来的调用情况。
可见,我们上面所设想的两个方案都不可行。
我们希望:
-
(1)编写调用子程序的程序的时候不必关心子程序到底使用了哪些寄存器。
-
(2)编写子程序的时候不必关心调用者使用了哪些寄存器。
-
(3)不会发生寄存器冲突。
3.2.3 给出解决方案。
解决这个问题的简捷方法是,在子程序的开始将子程序中所有用到的寄存器中的内容都保存起来,在子程序返回前再恢复。可以用栈来保存寄存器中的内容。
3.2.4 子程序的标准框架
以后,我们编写子程序的标准框架如下:
3.2.5 改进之前的程序
我们改进一下子程序 capital的设计:
capital: push cxpush sichange: mov cl,[si]mov ch, 0jcxz okand byte ptr [si], 11011111binc sijmp short capitalok: pop sipop cxret
要注意寄存器入栈和出栈的顺序。
结语
今天的分享到这里就结束啦!如果觉得文章还不错的话,可以三连支持一下。
也可以点点关注,避免以后找不到我哦!
Crossoads主页还有很多有趣的文章,欢迎小伙伴们前去点评,您的支持就是作者前进的动力!
相关文章:
【汇编语言】call 和 ret 指令(三) —— 深度解析汇编语言中的批量数据传递与寄存器冲突
文章目录 前言1. 批量数据的传递1.1 存在的问题1.2 如何解决这个问题1.3 示例演示1.3.1 问题说明1.3.2 程序实现 2. 寄存器冲突问题的引入2.1 问题引入2.2 分析与解决问题2.2.1 字符串定义方式2.2.2 分析子程序功能2.2.3 得到子程序代码 2.3 子程序的应用2.3.1 示例12.3.2 示例…...
定义函数合并字符串—超详细讲解
【问题描述】 编写一个函数void str_bin(char str1[ ], char str2[ ]), str1、str2是两个有序字符串(其中字符按ASCII码从小到大排序),将str2合并到字符串str1中,要求合并后的字符串仍是有序的,允许字符重…...
实现 vue3 正整数输入框组件
1.实现代码 components/InputInteger.vue <!-- 正整数输入框 --> <template><el-input v-model"_value" input"onInput" maxlength"9" clearable /> </template><script lang"ts" setup> import { ref …...
Leetcode - 周赛425
目录 一,3364. 最小正和子数组 二, 3365. 重排子字符串以形成目标字符串 三,3366. 最小数组和 四,3367. 移除边之后的权重最大和 一,3364. 最小正和子数组 本题可以直接暴力枚举,代码如下: …...
c++(斗罗大陆2)
我把魂力等级更新到了31级 #include<iostream> #include<conio.h> #include<windows.h> #include<stdlib.h> #include<stdio.h> #include<time.h> #include<string.h> using namespace std; int qs10; int xthl0;//先…...
redis常见数据类型
Redis是一个开源的、内存中的数据结构存储系统,它可以用作数据库、缓存和消息代理,支持多种数据类型。 一、数据类型介绍 String(字符串) Redis中最基本的数据类型。可以存储任何类型的数据,包括字符串、数字和二进制…...
MySQL - 性能优化
使用 Explain 进行分析 Explain 用来分析 SELECT 查询语句,开发人员可以通过分析 Explain 结果来优化查询语句。 比较重要的字段有: select_type : 查询类型,有简单查询、联合查询、子查询等 key : 使用的索引 rows : 扫描的行数 type :…...
Linux进程概念-详细版(一)
目录 进程概念 描述进程-PCB task_struct-PCB的一种 task_struct内容分类 查看进程 通过系统目录查看 通过ps命令查看 通过系统调用获取进程的PID和PPID 通过系统调用创建进程 fork的认识 使用if进行分流 最后的总结 Linux进程状态 运行状态-R 浅度睡眠状态-S 深度睡…...
K8S网络系列--Flannel网络下UDP、VXLAN模式的通信流程机制分析
文章目录 前言一、了解overlay、underlay容器网络二、网络通信1.分类2.网络虚拟设备对2.1、什么是网络虚拟设备对veth pair?2.2、如何查看容器的网卡与主机的哪个veth设备对是成对的关系? 3、vxlan和vtep3.1、vtep3.2、vxlan相关概念 三、Flannel网络模式剖析0、flannel的作用…...
ThreadLocal的设计思考
问题的提出 在Java多线程中,共享变量的读写非常容易出现不可预测的行为,因此对共享变量的访问控制非常重要。因此在多线程编程时,为了保证线程安全,需要进行额外的同步措施。比如典型的操作就是加锁。除了加锁外,另一…...
shell脚本练习(2)
1. 使用case实现成绩优良差的判断 2. for创建20用户 用户前缀由用户输入 用户初始密码由用户输入 例如:test01,test10 3. for ping测试指网段的主机 网段由用户输入,例如用户输入192.168.2 ,则ping 192.168.2.10 --- 192.168.2.2…...
通讯专题4.1——CAN通信之计算机网络与现场总线
从通讯专题4开始,来学习CAN总线的内容。 为了更好的学习CAN,先从计算机网络与现场总线开始了解。 1 计算机网络体系的结构 在我们生活当中,有许多的网络,如交通网(铁路、公路等)、通信网(电信、…...
Harmony NEXT-越过相机读写权限上传图片至项目云存储中
问题成因 在制作用户注册登录界面时想要实现用户头像上传共能,查询API文档,发现有picker和PhotoAccessHelper两个包可以选择使用,但是在使用PhotoAccessHelper包拉起相册并读入所选的照片后将该照片传入云存储中产生报错,需要相册…...
MATLAB基础应用精讲-【数模应用】Retinex图像去雾算法(附MATLAB和python代码实现)
目录 前言 算法原理 图像去雾 数学模型 算法步骤 算法拓展 多尺度Retinex (MSR) 算法 MSR算法的实现细节 McCann Retinex 算法 McCann99 Retinex算法 基于暗通道先验的图像去雾算法 暴力解法——直方图均衡化去雾 基于Retinex理论的图像去雾 基于暗通道先验的单…...
点击A组件跳转到B页面的tab的某一列
1、使用vuex存储点击的数据; 点击A组件里面的button按钮: <div><button click"banli(first)">已办理</button><button click"banli(second)">未办理</button><button click"banli(third)&quo…...
HarmonyOS xml转换JavaScript 常用的几个方法
HarmonyOS 使用 xml转换JavaScript 的好处 易用性: 提供了简洁的API接口,使得XML到JavaScript对象的转换变得简单直接。转换选项的灵活性允许开发者根据实际需求自定义转换结果。 高效性: HarmonyOS对底层运行时环境进行了优化,使…...
Linux笔记---进程:进程等待
1. 进程等待的概念 进程等待是指父进程通过系统调用wait或waitpid来对子进程进行状态检测与回收的功能。 当子进程退出时,如果父进程不读取子进程的退出状态,子进程就会成为僵尸进程,造成内存泄漏的问题。因此,父进程需要调用wa…...
【Linux】匿名管道通信场景——进程池
🔥 个人主页:大耳朵土土垚 🔥 所属专栏:Linux系统编程 这里将会不定期更新有关Linux的内容,欢迎大家点赞,收藏,评论🥳🥳🎉🎉🎉 文章目…...
算法妙妙屋-------1.递归的深邃回响:全排列的奇妙组合
全排列的简要总结 全排列(Permutation)是数学中一个经典的问题,指的是从一组元素中,将所有元素按任意顺序排列形成的所有可能序列。 特点 输入条件: 给定一组互异的元素(通常为数组或字符串)。…...
【maven-6】Maven 生命周期相关命令演示
Maven 是一个广泛使用的项目管理工具,尤其在 Java 项目中。它通过定义一系列的生命周期阶段(Phases)来管理项目的构建过程。理解这些生命周期阶段及其相关命令,对于高效地构建和管理项目至关重要。本文将通过实际演示,…...
黑马程序员Java笔记整理(day06)
1.继承的特点 2.继承的权限 3. 4.小结 5.方法重写 6.子类构造器 7.兄弟构造器 8.多态 9.小结...
LeetCode【代码随想录】刷题(动态规划篇)
509. 斐波那契数 力扣题目链接 题目:斐波那契数(通常用F(n)表示)形成的序列称为斐波那契数列 。该数列由0和1开始,后面的每一项数字都是前面两项数字的和。也就是: F(0) 0,F(1) 1 F(n) F(n - 1) F(n…...
【看海的算法日记✨优选篇✨】第三回:二分之妙,寻径中道
🎬 个人主页:谁在夜里看海. 📖 个人专栏:《C系列》《Linux系列》《算法系列》 ⛰️ 一念既出,万山无阻 目录 📖一、算法思想 细节问题 📚左右临界 📚中点选择 📚…...
基于yolov8、yolov5的铝材缺陷检测识别系统(含UI界面、训练好的模型、Python代码、数据集)
摘要:铝材缺陷检测在现代工业生产和质量管理中具有重要意义,不仅能帮助企业实时监控铝材质量,还为智能化生产系统提供了可靠的数据支撑。本文介绍了一款基于YOLOv8、YOLOv5等深度学习框架的铝材缺陷检测模型,该模型使用了大量包含…...
计算机光电成像理论基础
一、透过散射介质成像 1.1 光在散射介质中传输 光子携带物体信息并进行成像的过程是一个涉及光与物质相互作用的物理现象。这个过程可以分为几个步骤来理解: 1. **光的发射或反射**: - 自然界中的物体可以发射光(如太阳)&am…...
【QNX+Android虚拟化方案】125 - 如何创建android-spare镜像
【QNX+Android虚拟化方案】125 - 如何创建android-spare镜像 1. Android侧创建 (ext4 / sparse) test_img.img 镜像 方法一2. Android侧创建 (ext4 / sparse) test_img.img 镜像 方法二3. qnx 侧 分区透传Android 配置3.1 配置分区透传3.2 Android 侧分区 rename3.3 创建挂载目…...
深度学习基础小结_项目实战:手机价格预测
目录 库函数导入 一、构建数据集 二、构建分类网络模型 三、编写训练函数 四、编写评估函数 五、网络性能调优 鲍勃开了自己的手机公司。他想与苹果、三星等大公司展开硬仗。 他不知道如何估算自己公司生产的手机的价格。在这个竞争激烈的手机市场,你不能简单地…...
EMall实践DDD模拟电商系统总结
目录 一、事件风暴 二、系统用例 三、领域上下文 四、架构设计 (一)六边形架构 (二)系统分层 五、系统实现 (一)项目结构 (二)提交订单功能实现 (三࿰…...
【随笔】AI技术在电商中的应用
这几年,伴随着ChatGPT开始的AI浪潮席卷全球,从聊天场景逐步向多场景扩散,形成了广泛开花的现象。至今,虽然在部分场景的进展已经略显疲态,但当前的这种趋势仍然还在不断的扩展。不少公司,甚至有不少大型电商…...
序列式容器详细攻略(vector、list)C++
vector std::vector 是 STL 提供的 内存连续的、可变长度 的数组(亦称列表)数据结构。能够提供线性复杂度的插入和删除,以及常数复杂度的随机访问。 为什么要使用 vector 作为 OIer,对程序效率的追求远比对工程级别的稳定性要高得多,而 vector 由于其对内存的动态处理,…...
网站建设初衷/淘宝店铺运营推广
解决步骤:1、top命令查看CPU占用情况可以看到11042进程占用了非常多的CPU资源2、查看F5并发曲线:为什么应用耗费了这么多的线程,难道是用户量突然上来了,调取了F5的访问曲线图,可以看到在15:57左右并发量突然猛涨&…...
网站建设的开发语言/全网软文推广
An error happened during template parsing (template: “class path resource [templates//index.html]” - line 129, col 9) 出现这个问题我一开始以为是Thymeleaf模板没声明或者其他问题,搞了半小时才发现是th:if"${map.post.status1}"少了个"…...
asp网站本地测试修改视频教程/网络文章发布平台
今天,数据库的操作越来越成为整个应用的性能瓶颈了,这点对于Web应用尤其明显。关于数据库的性能,这并不只是DBA才需要担心的事,而这更是我们程序 员需要去关注的事情。当我们去设计数据库表结构,对操作数据库时(尤其是…...
wordpress调用 php文件上传/百度下载安装到手机
事件: 由于前一天的晚上加班了、第二天又接着上班、所以精神上有点不在状态;收到客户的反馈说在slave上找不到master刚刚插入的数据; 阶段1: 遇到这事的第一感觉就是这可能是主从延时、或是slave的复制出错了使得数据没有同步、于…...
电子商务网站建设规划书/全球搜
1、模块 模块尽量使用小写命名,首字母保持小写,尽量不要用下划线(除非多个单词,且数量不多的情况) # 正确的模块名 import decoder import html_parser# 不推荐的模块名 import Decoder 2、类名 类名使用驼峰(CamelCase)命名风格,…...
网站ie浏览器不兼容/深圳seo顾问
今天无意中发现一个好玩的照片,可能有人玩過了 -v- 但真的蛮有意思的——————–先看看這張圖然後如果你有戴眼鏡拿掉再看一次如果你看到了二張不同的圖恭喜你 你真的近視了(這句話是對還沒戴眼鏡而近視的人說的)(一般人應該會先看到 愛因斯坦 近視或…...