(十)汇编语言——CALL和RET指令

news/2024/2/29 2:48:20

(十)汇编语言——CALL和RET指令

文章目录

  • (十)汇编语言——CALL和RET指令
    • CALL指令
      • 功能
        • 寄存器
        • 内存
      • 段间转移
    • 返回指令
      • ret
      • retf
    • 实例
    • MUL指令
    • 模块化程序设计
      • 寄存器
      • 内存单元
    • 寄存器冲突问题
      • 方法

相信大家肯定在C语言里面接触过函数这个概念,或者是一些高级语言里面的方法,那么汇编语言有没有这样类似的概念呢,答案是当然的,接下来就让我们来介绍一下汇编的模块化程序设计。

CALL指令

这个CALL指令呢,我们是第一次接触,它主要的作用就是调用子程序,实质上就是进行流程转移,而且实现转移的方法和jmp指令的原理相似。使用的格式就是call 标号,这个就类似于,把当前位置保存起来,去执行其他地方的代码,执行完了之后再回到原处去执行。就类似于我们的中断。

功能

首先将当前的IP压入栈中,然后转移到标号处执行指令。相当于下面的语句。实现的是段间转移,如果我们要实现段内转移呢?我们继续讲解。

  1. (sp)=(sp)–2
  2. ((ss)*16+(sp))=(IP)
  3. (IP)=(IP)+16位位移
push IP
jmp near ptr 标号

寄存器

而如果转移地址在寄存器里面的话,就有一点不一样了,但是和我们之前介绍的 jmp 指令类似的,我们具体看看吧!就相当于下面的语句。

push IP
jmp 16位寄存器

内存

转移地址在内存中的call指令其实也是类似的,我们给出相应的语句,相信大家可以很清楚的理解到。

;call word ptr 内存单元地址
push IP
jmp word ptr 内存单元地址;calld word ptr 内存单元地址
push CS
push IP
jmp dword ptr 内存单元地址

段间转移

我们如果想要实现段间转移的话,使用的指令就是call far ptr 标号,这个时候,我们就会把CS和IP同时入栈保存起来。具体步骤如下所示:

  • (sp)=(sp)–2
  • ((ss)×16+(sp))=(CS)
  • (sp)=(sp)–2
  • ((ss)×16+(sp))=(IP)
  • (CS)=标号所在的段地址
  • (IP)=标号所在的偏移地址
push CS
push IP
jmp far ptr 标号

“call 标号”类似”jmp near ptr 标号”,对应的机器指令中为相对于当前IP的转移位移,而不是转移的目的地址,实现段内转移。而指令“call far ptr 标号”实现的是段间转移!

返回指令

我们这里主要介绍ret指令和retf指令。

ret

用栈中的数据,修改IP的内容,从而实现近转移,相当于 pop IP。

retf

用栈中的数据,修改CS和IP的内容,从而实现远转移;

实例

这个程序就是计算一下ax的平方,但是值得注意的就是,这里我们用到了栈段,因为我们的call 指令和ret指令需要入栈和出栈操作。

assume cs:code, ss:stack
stack segmentdb 8 dup(0)db 8 dup(0)
stack ends
code segmentstart :mov ax, stackmov ss,axmov sp,16mov ax,1000call smov ax, 4c00hint 21hs:add ax,axretcode ends
end start

MUL指令

mul指令就是我们的乘法指令,我们之前介绍过除法div指令,我们来简单回顾一下。

被除数AXDX和AX
除数8位内存或寄存器16位内存或寄存器
ALAX
余数AHDX

而接下来我们介绍的乘法指令与这个类似,我们来看看吧!

被乘数ALAX
除数8位内存或寄存器16位内存或寄存器
结果AXDX(高位)和AX(低位)

我们来看一个例子吧!计算100乘10和100乘10000。

;100*10
mov al,100
mov bl,10
mul bl;100*10000
mov ax,100
mov bx,10000
mul bx

模块化程序设计

我们知道,在程序设计中,模块化设计是十分重要的,那么,在汇编语言中有没有这要的设计呢?聪明的小伙伴们应该想到了,调用我们刚刚介绍的CALL 指令和RET指令即可。但是呢,需要我们去解决两个问题,那就是参数和返回值的问题,我们来看一下这两个问题我们如何来解决。

在这之前,我们来看一个问题,就是根据提供的N,计算N的3次方。我们可以考虑用循环去做,但是我们现在选择使用模块化程序设计的方法去解决,具体解决办法如下:

寄存器

把数据存储到寄存器里面是一个解决办法,我们来看看具体的操作。

  1. 首先把参数放到 bx 中,即(bx)=N;
  2. 然后子程序中用多个mul指令计算N3;
  3. 最后将结果放到dx和ax中:(dx:ax)=N3
assume cs:code
data segmentdw 1,2,3,4,5,6,7,8dd 0,0,0,0,0,0,0,0
data endscode segment
start:mov ax,datamov ds,axmov si,0     ;指向第一组单词mov di,16    ;指向第二组单词mov cx,8s:mov bx,[si]call cubemov [di],axmov [di].2,dxadd si,2add di,4loop s        ;循环处理mov ax,4c00hint 21hcube:mov ax,bxmul bxmul bxretcode ends
end start

这样处理当然是没有问题的,但是会面临一个问题,就是我们的寄存器只有那么多,如果需要传递的东西比较多,寄存器不够用了怎么办,确实这是我们会遇到的问题。既然寄存器比较少,我们就换一个方法,使用内存单元去传递信息。

内存单元

为了避免寄存器不够的尴尬,于是我们现在使用内存单元去传递数据。我们的做法就是先将批量数据放到内存中,然后将它们所在内存空间的首地址放在寄存器中,传递给需要的子程序。对于具有批量数据的返回结果,也可用同样的方法。

比如我们看这个例子,将data段中的字符串转化为大写。

data segmentdb 'conversation'
data ends

我们来看一下具体的代码段怎么去写。

code segment
start:mov ax,datamov ds,axmov si,0mov cx,12;循环次数call capitalmov ax,4c00hint 21h
capital: and byte ptr [si],11011111b;变大写inc siloop capitalret
code ends

目前这样基本上是没有什么问题了。但是我们还要介绍另外一种方法,那就是通过我们的栈来实现传递参数。

接下来我们就使用栈来进行参数传递,主要的原理就是由调用者将需要传递给子程序的参数压入栈中,子程序从栈中取得参数。同样的,我们介绍一个例子,那就是计算(a–b)3,a、b为word型数据。我们来看一下代码段部分。

code segment
start:mov ax,1push axmov ax,3push ax;首先将一些数据入栈call difcube;调用子程序mov ax,4c00hint 21hdifcube:push bp;先在栈中保存BP的值mov bp,spmov ax,[bp+4]sub ax,[bp+6]mov bp,axmul bpmul bp;获得参数并计算,返回到AX中pop bp;恢复之前的BP值ret 4;放弃入栈的参数
code ends

好啦,这就是关于用栈来传递参数的方法,我们就介绍到这。

寄存器冲突问题

接下来我们将来解决有关寄存器冲突的问题,具体来说就是避免在子程序里面使用的寄存器与主程序里面使用的寄存器冲突了,导致程序无法运行。好啦,接下来我们就会来介绍如何解决这个问题。给大家一个提示,那就是使用我们经常使用的栈来保存数据。

方法

前面说了,我们是使用栈去解决这个问题,那么就让我们来卡看具体如何使用吧。

子程序开始:

  1. 子程序中使用的寄存器入栈
  2. 子程序内容
  3. 子程序使用的寄存器出栈
  4. 返回(ret、retf)
capital:push cxpush si
change:mov cl,[si]mov ch,0jcxz okand byte ptr [si],11011111binc sijmp short change
ok:pop sipop cxret

大家看这个地方,原理就是用栈先去保存数据,然后在程序结束的时候再把原来的数据出栈。
子程序中使用的寄存器入栈
2. 子程序内容
3. 子程序使用的寄存器出栈
4. 返回(ret、retf)

capital:push cxpush si
change:mov cl,[si]mov ch,0jcxz okand byte ptr [si],11011111binc sijmp short change
ok:pop sipop cxret

大家看这个地方,原理就是用栈先去保存数据,然后在程序结束的时候再把原来的数据出栈。


http://www.ppmy.cn/news/12798.html

相关文章

【7】SCI易中期刊推荐——计算机 | 人工智能(中科院4区)

🚀🚀🚀NEW!!!SCI易中期刊推荐栏目来啦 ~ 📚🍀 SCI即《科学引文索引》(Science Citation Index, SCI),是1961年由美国科学信息研究所(Institute for Scientific Information, ISI)创办的文献检索工具,创始人是美国著名情报专家尤金加菲尔德(Eugene Garfield…

DRG在医保支付中的应用

DRG在医保支付中的应用 前言 DRG全称是“按疾病诊断相关分组”,它根据病人的年龄、性别、住院天数、临床诊断、病症、手术、疾病严重程度、合并症与并发症、转归等因素把病人分入不同的诊断相关组。DRG与医保支付结合,形成DRGs-PPS制度(Diag…

实现PHP爬虫小技巧

现在学习爬虫的小伙伴很多,但是奈何实力不均匀,这也是造就了不同的人编写不同的代码,样式各种各样。造成这样的结果不仅仅是因为个人技术原因,也有是因为选择的语言不同导致差异化。 对于新手来说用PHP来写爬虫非常友好&#xff…

测试——自动化测试(Selenium工具)

目录 一、自动化测试的概念以及分类 二、Selenium—web自动化测试工具 1、自动化测试的一些前置工作 2、第一个自动化实例 3、总结​编辑 三、 Selenium常用方法 定位元素的方法 元素的操作 等待 强制等待(待补充) 隐式等待(待补充&…

在WPS表格里制作连接到openGauss的实时刷新报表

前言 其实我的数据库启蒙,是在一家甲方公司。 当时一进这家公司,就见到了通过连接数据库自动刷新的excel表。当时学会了这招就一发不可收拾,制作出各种自动刷新的报表。 想象一下,有些高管不喜欢打开各种复杂的业务系统或者报表系…

移动端App自动化之触屏操作自动化

工作中我们经常需要对应用的页面进行手势操作,比如滑动、长按、拖动等,AppiumDriver 为我们提供一个模拟手势操作的辅助类TouchAction,可以通过它对手机屏幕进行手势操作。具体用法参见链接:chromedriver下载地址与webview自动化关…

【C语言课程设计】通讯录(1.0版本)

前言 相信各位对于通讯录都不是很陌生吧。通讯录我们在学校的大作业,课程设计经常会去使用它。那么今天我们将使用C语言来实现一个简单的通讯录。 目录 前言 一、通讯录的需求 二、工程文件的创建 三、通讯录的声明和定义 四、通讯录各函数的声明和定义 五、通…

HTML实现除夕最美烟花,2023春节倒计时,新年不可没有烟花,最炫烟花代码分享

📋 前言 🖱 博客主页:在下马农的碎碎念✍ 本文由在下马农原创,首发于CSDN📆 首发时间:2023/01/17📅 最近更新时间:2023/01/17🤵 此马非凡马,房星本是星。向前…

《MongoDB入门教程》第23篇 聚合统计之$sum表达式

本文将会介绍如何利用 $sum 表达式计算一组数值的总和。 $sum 表达式 MongoDB 支持 $sum 表达式&#xff0c;用于返回一组数值的总和。该表达式的语法如下&#xff1a; { $sum: <expression> }如果汇总的字段包含非数值内容&#xff0c; $sum 表达式会忽略相应的内容。…

YOLOV8——快速训练指南(上手教程、自定义数据训练)

概述 本篇主要用于说明如何使用自己的训练数据&#xff0c;快速在YOLOV8 框架上进行训练。当前&#xff08;20230116&#xff09;官方文档和网上的资源主要都是在开源的数据集上进行测试&#xff0c;对于算法“小白”或者“老鸟”如何快速应用到自己的项目中&#xff0c;这…

事关网站数据安全,你真的了解https与SSL证书之间的关系吗?

虽然根据网上的建站教程&#xff0c;大多数站长都知道要给域名添加一个SSL证书&#xff0c;以此来开启https进而可以获得更好的用户体验以及提高网站的安全性。但是SSL证书为什么能使得网站https&#xff1f;你真的去细究过两者之间的关系吗&#xff1f;本文就来说说https与SSL…

【PaaS】分享一家最近发现的宝藏Paas厂家

目录 一、结识独自开 二、独自开的介绍 三、独自开的需求 四、独自开注册流程 五、神仙公司独自开 一、结识独自开 算是机缘巧合&#xff0c;我被C站白佬拉入了他的聊天群&#xff0c;群内均是来自于CSDN的不同领域的优质作者&#xff0c;其中不乏相关领域工作多年的老工程…

基于混沌系统和DNA算法的RGB图像加密(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 本文介绍了基于混沌系统和DNA编码的彩色数字图像加密、解密、抗噪声性能分析以及抗裁剪性能分析。 &#x1f4da;2 运行结果 &…

maven依赖设置

之前说过了可以通过依赖的方式将一个大程序分为多个小的模块&#xff0c;模块之间可以利用依赖链接在一起。 但是如果有多个依赖的情况下会怎么样呢&#xff1f; A依赖于B、C&#xff0c;而B、C又有各自的依赖&#xff0c;那么A是否依赖于B、C的依赖呢&#xff1f; 答案是是的…

纯净版ISO镜像下载大全(Windows、Linux、mac)

目录 一、前言介绍 前言必读 介绍 二、获取ISO镜像方式 &#xff08;一&#xff09;官方镜像下载 &#xff08;二&#xff09;看评论区获取下载 回复内容&#xff08;都是小写&#xff09; Windows操作系统 1.windows XP系统 2.Windows 7系统 3.Windows10系统 4.W…

列表元素的最大值,最小值,出现的次数和列表长度

1 获取列表中的最大元素和最小元素&#xff1a; 使用max和min可以分别获取一个列表中最大元素和最小元素的值&#xff0c;其语法格式为&#xff1a; max(list) 和min(list) 例&#xff1a;ls[12,34,56,87]#创建列表并赋给ls print(ls中最大元素值为&#xff1a;max(ls))#输出…

基于迁移学习的人脸识别实战(完整代码+数据)

迁移学习概述 想给家里的小八爪机器人加上人脸识别功能,比如瞄准的是我时就不能发射炮弹,这样儿子就没法拿这个怪物打我了。。。(也可以在工位上加个摄像头,领导来了提前报警。。。) 人脸识别跟普通的图像识别还是有相似的地方,比如都是图像 cnn 卷积池化;但也有很多不同…

蓝桥杯 stm32 实现 ADC 采集数据功能 CubeMX

文章内的代码使用 HAL 库。 ADC 即 模数转换器&#xff0c;是指 将 连续变化的模拟信号 转换成 离散的数字信号 的器件。 文章目录前言一、ADC 原理图二、CubeMX 配置三、ADC 代码讲解总结前言 一、ADC 原理图 从原理图我们可以看到 STM32G431 内部集成 两个 最高位 12 位 的 A…

【计算机体系结构-01】指令集体系结构、微体系结构简介

1. “虚拟” to “现实” 首先可以看这张图片&#xff0c;下面的 Physics 所指的是我们的物理世界中看得见摸得到或者是客观存在的事物&#xff0c;而人类希望将自己的工作内容或者需求以某种方式映射到物理层面上&#xff0c;用物理变化带来的影响来完成人类工作内容。例如早期…

【高并发内存池】第一弹之定长内存池

#define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<vector> #include<time.h> using std::cout; using std::endl;#ifdef _WIN32#include<windows.h> #else // #endif// 直接去堆上按页申请空间 inline static void* SystemAlloc(size_t…
最新文章