汇编语言程序设计(三)之汇编程序

news2024/12/28 3:54:48

系列文章

汇编语言程序设计(一)
汇编语言程序设计(二)之寄存器

汇编程序

经过上述课程的学习,我们可以编写一个完整的程序了。这章开始我们将开始编写完整的汇编语言程序,用编译和连接程序将它们连接成可执行文件(如.exe文件)在DOS中运行。为了能够透彻地理解一个完整的程序(尽管它看上去十分简单),我们将经历一个漫长的过程。

1. 汇编程序的执行过程

下图描述了一个汇编程序从写出到最终执行的简要过程:

在这里插入图片描述
第一步:编写汇编源程序

使用文本编辑器(记事本、Notepad++等等),用汇编语言编写汇编源程序。这一步的工作是产生了一个存储源程序的文本文件

第二步:对源程序进行编译连接

使用汇编语言编译程序对源程序文件中的源程序进行编译,产生目标文件;再用连接程序对目标文件进行连接,生成可在操作系统直接运行的可执行文件。

可执行的文件包含两部分内容:

  • 程序和数据:程序中的汇编指令翻译过来的机器码和源程序中定义的数据
  • 相关的描述信息:程序多大,要占用多少内存空间等

三步:执行可执行文件中的程序

在操作系统中,执行可执行文件中的程序。此时,操作系统依照可执行文件中的描述信息,将可执行文件中的机器码和数据加载入内存,并进行相关的初始化(比如CS:IP指向第一条要执行的指令),然后由CPU执行程序。

2. 源程序

下面我们来看一下一段简单的程序:

assume cs:codesg
codesg segment
    mov ax,0123H
    mov bx,0456H
    add ax,bx
    add ax,ax
    
    mov ax,4C00H
    int 21H
codesg ends
end

下面来对这个程序进行说明。在汇编语言程序中,包含两种指令,一种是汇编指令,一种是伪指令。汇编指令是有对应机器码的指令,可以被编译成机器指令,最终被CPU执行。而伪指令并没有对应的机器码,最终不会被CPU执行,而是会被编译器所执行。

  • 我们先来看一下上述程序中出现的伪指令
  1. xxx segment

    xxx ends
    segment 和 ends 是成对使用的伪指令,这是在写可被编译器编译的汇编程序时必须要用到的一对伪指令。segment和ends的功能是定义一个段,segment说明一个段的开始,ends说明一个段的结束。在汇编源程序中,一个段必须要有一个名称标识,使用格式为:

段名 segment

段名 ends

像上述的程序中:(定义了一个代码段)

codesg segment  ;定义了一个段,段的名称为codeseg,这个段从此开始
  ;..
codesg ends ;名称为codeseg的段到此结束

当然一个源程序可以由多个段组成,可以用来存放代码、数据或者当做栈空间来使用。一个汇编源程序至少要有一个段:代码段。

2.end
end是一个汇编程序的结束标记,编译器在编译汇编程序的时候,如果碰到end,就会结束对源程序的编译。所以,我们在写程序的时候,程序结束的时候应该在结尾处加上伪指令end。

3.assume
assume:假设,它可以用来假设某一段寄存器和程序中的某一个用segment…ends定义的段相关联。在编程时,我们需要使用assume将有特定用途的段和相关的段寄存器关联起来。

例如上述程序中定义了一个名为codesg的代码段,我们需要将CS段寄存器和该段进行关联,格式则为:

assume cs:codesg

如果你要关联多个段:可以使用如下格式:

assume cs:codesg ds:datasg ss:stacksg

  • 除了伪指令以外,还有最重要的汇编指令

编程的最终目的是让计算机完成一定的任务,而任务的完成由汇编指令来指示。汇编指令经过编译连接之后会转换成对应的机器码,如下图所示:

在这里插入图片描述
除了上述内容以外,我们还需要知道codesg的具体含义

它被称为标号。一个标号指代了一个地址。上述示例中codesg在segment前面,作为一个段的名称,最终在编译连接之后处理为一个段的段地址

认识上述的指令之后,我们再来看一下汇编程序的结构,从整体上来看一个汇编源程序应该需要什么

1.定义一个段(当然可以有多个段,但至少要有一个代码段

;比如  定义了一个段,段名为abc
abc segment
;..
abc ends

2.往段中加入汇编指令

abc segment
    mov ax,2    ;这三条汇编语句的作用是求2^3
    add ax,ax
    add ax,ax
abc ends

3.指明程序在何处结束

abc segment
    mov ax,2    ;这三条汇编语句的作用是求2^3
    add ax,ax
    add ax,ax
abc ends
end

4.指明代码段:人为设置代码段编译器并不会也这么认为

assume cs:abc
abc segment
    mov ax,2    ;这三条汇编语句的作用是求2^3
    add ax,ax
    add ax,ax
abc ends
end


5.程序返回
上述讲解我们并没有讲述下面两条语句的作用,它们的作用是程序返回,类似于C语言中的return

mov ax,4C00H
int 21H

当然我们不用过多探究它们具体是什么意思,我们知道它们的功能是程序返回就可以了。所以上述程序还可以完善:(到此为止我们才算完成了一个较为完整的汇编源程序)

assume cs:abc
abc segment
    mov ax,2    ;这三条汇编语句的作用是求2^3
    add ax,ax
    add ax,ax

    mov ax,4c00H
    int 21H
abc ends
end
源程序和程序的区别:我们称源程序文件中的所有内容成为源程序,比如1.asm中的内容。将源程序中

最终由计算机执行、处理的指令或数据称为程序。

到此为止,我们已经接触了几个和结束相关的内容:段结束、程序结束、程序返回,下图展示了它们的区别:

在这里插入图片描述

3. 编译

上节内容已经可以完成一个源程序的编写,我们将其保存为1.asm之后就可以得到一个源程序文件。在这之后我们就可以对其进行编译了,下面我们来讲解编译过程。编译需要借助于相应的编译器,我们采用的masm汇编编译器。在上一章中我们已经讲解了如何进行源程序的编译连接过程,现在我们来详细看看编译的过程

进入DOS,并且进入到MASM目录(我们放在虚拟C盘中,如果不是的可以使用cd指令进入对应的目录)

在这里插入图片描述
如上图,运行masm后,首先显示出一些版本信息,然后提示输入将要被编译的程序文件的名(【.ASM】)。我们默认的扩展名是asm,如果要编译的源程序文件名为p1.asm,在这里只要输入p1即可。如果源程序文件名字不是asm的扩展名则需要输入全名。比如文件名为p1.txt,就要输入全名。当然我们输入文件名的目的是让系统根据对应的文件名找到对应的文件,我们输入文件名的时候还需要指明,这个文件的所在路径,比如文件p1.txt在c:code\下,则输入应为:c:code\p1.txt,如果你的可执行文件和masm文件在同一级目录,则可以直接输入名字即可,后续中间文件.obj同理。

使用masm编译了源文件之后会生成一个目标文件.obj,我们也可以制定这个文件的名字,示意如下:

在这里插入图片描述
上述的图片中默认生成1.OBJ,我们也可以设置为其他名字。后续还会有两个提示,分别是提示生成列表文件和引用文件,当然我们可以直接忽略这两个文件,他们属于中间文件,之后一直按下Enter键即可。

最终出现如下界面:

在这里插入图片描述
当我们完成了上述步骤之后就会出现一个新的文件1.obj。当然如果编译过程中出现错误的话将不会生成最终的目标文件。程序出错的标志:

  • 程序中有Severe Errors

  • 找不到所给出的源程序文件

4. 连接

在对源文件进行编译得到目标文件之后,我们需要对目标文件进行连接,从而得到可执行文件。在这里我们需要使用到连接工具,文件名为LINK.EXE。下面我们来看看连接的过程。

在这里插入图片描述
输入link之后,系统提示你输入要进行连接的目标文件(【.OBJ】),而Run File这一行则是提示你是否要指定生成的可执行文件的名字,不指定则为【】中默认的名字,上述图示中为指定默认可执行文件名为1.exe,之后一直按Enter即可。

当然上述图片中有一个警告错误:没有栈段。在这里我们不用理会它。这之后将生成一个可执行文件1.exe,后续直接在命令行输入1.exe即可执行该可执行文件

关于连接的作用:(仅作了解)

  • 当源程序很大时,我们可以将它分为多个源程序进行编译,每个源程序都将产生一个目标文件,我们需要用连接程序将多个目标连接成一个可执行文件

  • 程序中调用了某个库文件中的子程序,需要将这个库文件和该程序生成的目标文件连接在一起,最终生成一个可执行文件

  • 一个源程序编译后,得到了存有机器码的目标文件,目标文件中的有些内容还不能直接用于生成可执行文件,需要经过连接程序将这些内容处理为最终的可执行信息。所以即使只有一个源文件和没有调用某个库的时候也需要进行连接

    简化编译和连接的方法:

  • 编译:masm 1.ASM;

  • 连接:link 1.OBJ;

    上述的两个指令制定了需要编译或者连接的文件,并且用;表示生成默认的文件,
    编译指令中;表示默认生成1.OBJ
    连接指令中;表示默认生成1.EXE
    效果如下图

在这里插入图片描述

5. 程序执行过程的跟踪

我们可以利用Debug来跟踪一个程序的运行过程,这通常是必须要做的工作。我们写的程序在逻辑上不一定总是正确的,对于简单的错误,仔细检查一下源程序即可发现。但是对于隐藏较深的错误,就需要对程序的执行过程进行跟踪分析才可以发现了。

这个过程我们需要借助工具debug。debug可以将程序加载入内存,设置CS:IP指向程序的入口。

具体用法如下图所示:

在这里插入图片描述

接下来可以使用R命令来看一下各个寄存器的设置情况,如下:

在这里插入图片描述

可以看到此时的CS:IP指向076A:0000内存单元,也就是说第一条要执行的指令在该地址单元中。仔细看最后面:076A:0000 B80200 MOV AX,0002,这里指示了第一条指令的地址、机器码、对应的汇编的指令我们可以用u命令看一下其它的指令,如下图:

在这里插入图片描述

我们可以看到076A:0000~076A:000A都是程序的机器码

到这里我们可以来进行跟踪了,使用T命令进行单步执行,并观察每条指令执行后对寄存器的影响。

当然,到了int 21这条指令时我们需要用P命令执行,如下图:

在这里插入图片描述

上图执行完INT 21之后显示出 “Program terminated normally”,返回到debug中。表示程序正常结束

当然,需要注意的是在执行INT 21这条语句时需要用P命令去执行。

练习:在这里大家可以通过调试一个汇编程序,在每步执行后,相关寄存器内容的改变。程序如下:

在这里插入图片描述

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

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

相关文章

反转链表——C语言经典单链表题目

首先,把oj题目的链接放在这,大家可以先去练习一下,再来看解析。 反转链表——力扣 题目:给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。 现在让我们来看一下解决代码,先看一下我写…

网上销售笔记本系统

技术:Java、JSP等摘要:本文讲述了基于B/S模式的笔记本电脑在线销售系统的设计与实现。所谓的笔记本电脑在线销售系统是通过网站推广互联企业的笔记本电脑和技术服务,并使客户随时可以了解企业和企业的产品,为客户提供在线服务和订…

04_Apache Pulsar的可视化监控管理、Apache Pulsar的可视化监控部署

1.4.Apache Pulsar的可视化监控管理 1.4.1.Apache Pulsar的可视化监控部署 1.4.Apache Pulsar的可视化监控管理 1.4.1.Apache Pulsar的可视化监控部署 第一步:下载Pulsar-Manager https://archive.apache.org/dist/pulsar/pulsar-manager/pulsar-manager-0.2.0/…

OpenCV-Python学习(22)—— OpenCV 视频读取与保存处理(cv.VideoCapture、cv.VideoWriter)

1. 学习目标 学习 OpenCV 的视频的编码格式 cv.VideoWriter_fourcc;学会使用 OpenCV 的视频读取函数 cv.VideoCapture;学会使用 OpenCV 的视频保存函数 cv.VideoWriter。 2. cv.VideoWriter_fourcc()常见的编码参数 2.1 参数说明 参数说明cv.VideoWr…

用代码实现解析解的方式求解_梯度下降法思路_导函数有什么用_接23节---人工智能工作笔记0026

这里24节,25节,介绍了一下人工智能高等数学要学习的一些内容,初步了解了一下,微积分中用到的知识~微分~以及导数这里... 然后接着23节,我们还是继续,走人工智能的主线,先把整体的人工智能的内容学习一遍,然后再去回去看数学知识更有目的性. 然后首先来回顾一下,这里机器学习,其…

为什么我给蓝牙芯片KT6368A发送AT指令没有反应呢

目录 一、问题描述简介 为什么我给蓝牙芯片KT6368A发送AT指令没有反应呢?查看了文档也没找到具体的解决办法 二、详细描述 这个问题,主要分为两个部分去考虑 KT6368A的芯片,上电是否正常,也就是有没有跑起来,这个详…

【ROS学习笔记11】ROS元功能包与launch文件的使用

【ROS学习笔记11】ROS元功能包与launch文件的使用 文章目录【ROS学习笔记11】ROS元功能包与launch文件的使用前言一、ROS元功能包二、ROS节点运行管理launch文件2.1 launch文件标签之launch2.2 launch文件标签之node2.3 launch文件标签之include2.4 launch文件标签之remap2.5 l…

Linux操作系统学习(进程间通信)

文章目录进程间通信进程通信的意义进程通信的方式1.基于文件的方式匿名管道命名管道2.基于内存的通信方式共享内存验证内核相关的数据结构了解进程间通信 进程通信的意义 ​ 当我们和另一个人打电话时两部手机都是独立的,通过基站传递信号等等复杂的过程就实现了通…

RPC重试机制和控制方案

重试机制 因为网络抖动等原因导致 RPC 调用失败,这时候使用重试机制可以提高请求的最终成功率,减少故障影响,让系统运行更稳定。 重试简易实现方案 在重试的过程中,为了能够在约定的时间内进行安全可靠地重试,在每次…

计算机科学导论笔记(二)

三、数据存储 3.1 数据类型 计算机行业中使用术语“多媒体”来定义包含数字、文本、音频、图像和视频的信息。 位:bit,binary digit的缩写,是存储在计算机中的最小单位,它是0或1. 位模式:为了表示数据的不同类型&a…

关于Paul C.R. - Inductance_ Loop and partial-Wiley (2009)一书的概括

环感抗和部分感抗是两种不同的电路元件,它们通常用于描述不同类型的导体结构中的电流承载能力。 环感抗通常用于描述绕制在磁性芯上的线圈。当电流通过线圈时,它会在磁性芯中产生一个磁场,这个磁场又会对线圈产生一个磁通量。这个磁通量的大…

八股文面试day1

二分查找(解决整数溢出) 方法一:mid(leftright)/2 -> left/2right/2 -> left(-left/2right/2) -> l(r-l)/2 方法二:mid(lr)>>>1 字节溢出整体右移一位就是正确的值 MySQL存储引擎MyISAM和InnoDB的区别 数据…

Raspberry Pi GPIO入门指南

如果您想使用 Raspberry Pi 进行数字输入/输出操作,那么您需要使用 GPIO(通用输入/输出)引脚。在这篇文章中,我们将为您提供 Raspberry Pi GPIO 的基础知识,包括如何访问和操作 GPIO 引脚。 0.认识GPIO 树莓派上的那…

MMSeg绘制模型指定层的Heatmap热力图

文章首发及后续更新:https://mwhls.top/4475.html,无图/无目录/格式错误/更多相关请至首发页查看。 新的更新内容请到mwhls.top查看。 欢迎提出任何疑问及批评,非常感谢! 摘要:绘制模型指定层的热力图 可视化环境安装 …

matlab - 程序流程控制、函数文件、特殊函数、调试与优化

学习视频MATLAB代码的两种执行方式:命令行、程序执行。1.程序流程控制1.1.m文件matlab中m文件分为两种:脚本文件&函数文件。脚本文件:实际上是一个命令的集合,可认为是命令行的改良版,方便我们去编写命令函数文件&…

守护进程 || 精灵进程

目录 守护进程(deamon) || 精灵进程 特点 什么是前台进程组 把自己写的服务器deamon deamon代码 守护进程(deamon) || 精灵进程 特点 01. 他的PPID是1(附件特征)02. COMMAND --- 称为进程启动的命令03…

[ vulnhub靶机通关篇 ] Empire Breakout 通关详解

🍬 博主介绍 👨‍🎓 博主介绍:大家好,我是 _PowerShell ,很高兴认识大家~ ✨主攻领域:【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 🎉点赞➕评论➕收藏 养成习…

应用层协议 HTTP HTTPS

目录 应用层 再谈 "协议" 序列化和反序列化 关于 json库 request序列化 request反序列化 response序列化 response反序列化 PS:命令宏 HTTP协议 认识URL urlencode和urldecode HTTP协议格式 HTTP请求 HTTP响应 请求方法 ​编辑 HT…

使用Element-UI展示数据(动态查询)

学习内容来源:视频P4 本篇文章进度接着之前的文章进行续写 精简前后端分离项目搭建 Vue基础容器使用 目录选择组件修改表格组件修改分页组件增加后端接口前端请求数据接口页面初始化请求数据点击页码请求数据选择组件 在官方文档中选择现成的组件,放在页…

XSS漏洞分类

XSS漏洞分类XSS分类反射型XSS反射XSS案例存储型XSS存储型XSS实操XSS分类 XSS根据类型和利用手法的不同,主要分为三大类: 反射型XSS存储型XSSDOM型XSS 反射型XSS 反射型XSS又称为非持久型XSS,是现在最容易出现的一种XSS漏洞。用户在请求某…