1-4、调试汇编程序

语雀原文链接

文章目录

    • 1、执行过程
      • 第一步:源程序
      • 第二步:编译连接
      • 第三步:执行
    • 2、DOSBox运行程序
      • 第1步 进入EDIT.EXE
      • 第2步 编写源程序
      • 第3步 编译
      • 第4步 连接
      • 第5步 执行
      • 完整过程
    • 3、DEBUG跟踪执行过程
      • 加载程序到内存
      • 执行程序
      • debug和源程序数字的默认进制
    • 4、DOS系统的shell

1、执行过程

  • 第一步:编写汇编源程序
  • 第二步:对源程序进行编译连接。使用汇编语言编译程序对源程序文件中的源程序进行编译,产生目标文件;再用连接程序对目标文件进行连接,生成可在操作系统中直接运行的可执行文件。可执行文件包含两部分内容。
    • 程序(从源程序中的汇编指令翻译过来的机器码)和数据(源程序中定义的数据)
    • 相关的描述信息(比如,程序有多大、要占用多少内存空间等)
  • 第三步:执行可执行文件中的程序。
    • 操作系统依照可执行文件中的描述信息,将可执行文件中的机器码和数据加载入内存,并进行相关的初始化(比如设置CS:IP指向第一条要执行的指令),然后由CPU执行程序。

image.png

第一步:源程序

  • 在汇编语言源程序中,包含两种指令,一种是汇编指令,一种是伪指令
  • 汇编指令是有对应的机器码的指令,可以被编译为机器指令,最终为CPU所执行
  • 伪指令没有对应的机器指令,最终不被CPU所执行。伪指令是由编译器来执行的指令,编译器根据伪指令来进行相关的编译工作。
  • 新建一个first.asm文件,内容如下
assume cs:codemsg
codemsg segment
    mov ax,0123H
    mov bx,0456H
    add ax,bx
    add ax,ax

    mov ax,4c00H
    int 21H

codemsg ends
end
  • 上述代码有3中伪指令

  • 第一条伪指令:assume这个伪指令的含义为"假设"。假设某一段寄存器和程序中的某一个用segment…ends定义的段相关联。上述代码中,用assume cs:codesg将把代码段的codesg和CPU中的段寄存器cs联系起来

  • 第二条伪指令:segment和ends是一对成对使用的伪指令,这是在写可被编记择器编译的汇编程序时,必须要用到的一对伪指令。segment和ends的功能是定义一个段,segment说明一个段开始,ends说明一个段结束。

  • 第三条伪指令:end是一个汇编程序的结束标记,编译器在编译汇编程序的过程中,如果碰到了伪指令end,就结束对源程序的编译。所以,在我们写程序的时候,如果程序写完了,要在结尾处加上伪指令end。否则,编译器在编译程序时,无法去知道程序在何处结束。注意,不要搞混了end和ends,ends是和segment成对使用的,标记一个段的结束,ends的含义可理解为"end segment"。我们这里讲的end的作用是标记整个程序的结束。

  • 基本格式如下

assume 段寄存器:xxx
xxx segment
	汇编指令
	...
	...
xxx ends
end

第二步:编译连接

  • 编译连接

image.png

第三步:执行

  • 可执行文件怎么才能运行?
  • 我们在DOS(一个单任务操作系统)的基础上,一个程序P2在可执行文件中,则必须有一个正在运行的程序P1,将P2从可执行文件中加载入内存后,将CPU的控制权交给P2,P2才能得以运行。P2开始运行后,P1暂停运行。而当P2运行完毕后,应该将CPU的控制权交还给使它得以运行的程序P1,此后,P1继续运行。
  • 一个程序结束后,将CPU的控制权交还给使它得以运行的程序,我们称这个过程为:程序返回。在程序的末尾添加返回的程序段就可以实现程序返回
    mov ax,4c00H
    int 21H

2、DOSBox运行程序

第1步 进入EDIT.EXE

  • 运行edit,IT/MASM文件中有几个EXE
    • DEBUG.EXE:debug执行程序
    • EDIT.EXE:编辑执行程序
    • LINK.EXE:连接执行程序
    • MASM.EXE:编译执行程序

image.png

Z:\>mount c d:\IT\MASM
Z:\>c:
Z:\>edit

第2步 编写源程序

  • 编写保存源程序

image.png

  • 保存到c:\first.asm

image.png

第3步 编译

  • 在编译一个源程序之前首先要找到一个相应的编译器。这里采用微软的masm5.0汇编编译器,文件名为MASM.EXE。这里我们把它放在c:\MASM.EXE
C:\>masm
Microsoft (R) Macro Assembler Version 5.00
Copyright (C) Microsoft Corp 1981-1985, 1987. All rights reserved.

Source filename [.ASM]: 
  • 运行masm后,首先显示出一些版本信息,然后提示输入将要被编译的源程序文件的名称。
  • [.ASM]提示我们,默认的文件扩展名是asm,如果要编译的源程序文件名是"pl.asm",只要在这里输入"pl"即可。可如果源程序文件不是以asm为扩展名的话,就要输入它的全名。比如源程序文件名为"pl.txt",就要输入全名。在输入源程序文件名的时候一定要指明它所在的路径。如果文件就在当前路径下,只输入文件名就可以,可如果文件在其他的目录中,则要输入路径。比如,要编译的文件pl.txt在"c:\windows/desktop"下,则要输入"c:/windows/desktop\pbl.txt"
  • 输入first,Enter回车3次即可
    • Object filename:编译出的目标文件名称,默认和源程序同名,直接回车即可;如果想自定义目标文件路径和名称,例如输入“c:\xx\out”
    • Source listing:编译程序提示输入列表文件的名称,这个文件是编译器将源程序编译为目标文件的过程中产生的中间结果。可以让编译器不生成这个文件,直接按Enter键即可。
    • Cross-reference:编译程序提示输入交叉引用文件的名称,这个文件同列表文件一样是编译器将源程序编译为目标文件过程中产生的中间结果。可以让编译器不生成这个文件,直接按Enter键即可。
  • 在编译的过程中,我们提供了一个输入,即源程序文件。最多可以得到3个输出:列表文件(.lst)、交叉引用文件(.crf)、目标文件(.obj)。这3个输出文件中,目标文件是我们最终要得到的结果,而另外两个只是中间结果,可以让编译器忽略对它们的生成。在汇编课程中,我们不讨论这两类文件。
C:\>masm
Microsoft (R) Macro Assembler Version 5.00
Copyright (C) Microsoft Corp 1981-1985, 1987. All rights reserved.

Source filename [.ASM]: first
Object filename [first.OBJ]:
Source listing  [NUL.LST]:
Cross-reference [NUL.CRF]:

	51798 + 464746 Bytes symbol space free

    	0 Warning Errors
    	0 Server  Errors
C:\>masm

第4步 连接

  • [.OBJ]:输入要连接的文件,此处输入first(无须后缀.OBJ)
  • Run File:输入要生成的可执行文件的名称,默认同名.EXE,直接Enter使用默认值
  • List File:连接程序提示输入映像文件的名称,这个文件是连接程序将目标文件连接为可执行文件过程中产生的中间结果,可以让连接程序不生成这个文件,直接按Enter键即可。
  • Libraries:如果程序中调用了某一个库文件中的子程序,就需要在连接的时候,将这个库文件和目标文件连接到一起,生成可执行文件。如果这个程序没有调用任何子程序,这里忽略库文件名的输入,直接按Enter键即可。
  • 最后输出一行警告:no stack segment,这里无需理会
C:\>link
Microsoft (R) Overly Linker Version 3.60
Copyright (C) Microsoft Corp 1981-1985, 1987. All rights reserved.

Object Module [.OBJ]: first
Run File [FIRST.EXE]:
List File [NUL.MAP]:
Libraries [.LIB]:
LINK : warning L4021: no stack segment
  • 连接有什么作用
      1. 当源程序很大时,可以将它分为多个源程序文件来编译,每个源程序编译成为目标文件后,再用连接程序将它们连接到一起,生成一个可执行文件;
      1. 程序中调用了某个库文件中的子程序,需要将这个库文件利该程序生成的目标文件连接到一起,生成一个可执行文件;
    • 3.一个源程序编译后,得到了存有机器码的目标文件,目标文件中的有些内容还不能直接用来生成可执行文件,连接程序将这些内容处理为最终的可执行信息。所以,在只有一个源程序文件,而又不需要调用某个库中的子程序的情况下,也必须用连接程序对目标文件进行处理,生成可执行文件。
  • 上述的编译和连接写法步骤比较多,可以简化以下,忽略一些过程
    • masm c:\first;
    • link first;
C:\>masm c:\first;
Microsoft (R) Macro Assembler Version 5.00
Copyright (C) Microsoft Corp 1981-1985, 1987. All rights reserved.

	51798 + 464746 Bytes symbol space free

    	0 Warning Errors
    	0 Server  Errors

C:\>link first;
Microsoft (R) Overly Linker Version 3.60
Copyright (C) Microsoft Corp 1981-1985, 1987. All rights reserved.

LINK : warning L4021: no stack segment

第5步 执行

  • 直接运行FIRST.EXE,输入first即可,这里也看不到任何结果
C:\>first

c:\>

完整过程

image.png

3、DEBUG跟踪执行过程

加载程序到内存

  • 在DOS中运行一个程序的时候,是由command将程序从可执行文件中加载入内存并使其得以执行。但是,这样我们不能逐条扣指令地看到程序的执行过程,因为command的程序加载,设置CS:IP指向程序的入口的操作是连续完成的,而当CS:IP一指向程序的入口,command就放弃了CPU的控制权,CPU了立即开始运行程序,直至程序结束。
  • DEBUG将程序FIRST.EXE加载入内存,进行相关的初始化后设置CS:IP指向程序的入口
c:\>debug first.exe
-r
AX=FFFF BX=0000 CX=000F DX=0000 SP=00FD BP=0000 SI=0000 DI=0000
DS=075A ES=075A SS=0769 CS=076A IP=0000 NV UP EI PL NZ NA PO NC
076A:0000 B82301		MOV		AX,0123
-u
076A:0000 B82301		MOV		AX,0123
076A:0003 BB5604		MOV		BX,0456
076A:0006 03C3			ADD		AX,BX
076A:0008 03C0			ADD		AX,AX
076A:000A B8004C		MOV		AX,4C00
076A:000D CD21			INT		21
076A:000F 0000		  ADD		[BX+SI],AL
076A:0011 0000		  ADD		[BX+SI],AL
076A:0013 0000		  ADD		[BX+SI],AL
076A:0015 0000		  ADD		[BX+SI],AL
076A:0017 0000		  ADD		[BX+SI],AL
076A:0019 0000		  ADD		[BX+SI],AL
076A:001B 0000		  ADD		[BX+SI],AL
076A:001D 0000		  ADD		[BX+SI],AL
076A:001F 0000		  ADD		[BX+SI],AL
  • 可以看到程序加载到内存从076A:0000~076A:000E,占据15个字节。CX=000F存储的就是程序的长度
  • 程序为何存储在076A:0000开始,可以看下图(图中有一步重定位没有写,这里不做介绍)

image.png

  • 程序加载后,DS=075A存放着程序所在内存区的段地址,这个内存区的偏移地址为0,所以这个内存区的地址为DS:0,也就是075A:0000
  • 这个内存区的前256个字节存放的是PSP(DOS用来和程序进行通信),从256个字节向后的空间放的是程序,所以程序真真是从075A+10H = 076A:0000开始的,所以CS=076A IP=0000,指向程序的第一条指令

执行程序

c:\>debug first.exe
-r
AX=FFFF BX=0000 CX=000F DX=0000 SP=0000 BP=0000 SI=0000 DI=0000
DS=075A ES=075A SS=0769 CS=076A IP=0000 NV UP EI PL NZ NA PO NC
076A:0000 B82301		MOV		AX,0123
-u
076A:0000 B82301		MOV		AX,0123
076A:0003 BB5604		MOV		BX,0456
076A:0006 03C3			ADD		AX,BX
076A:0008 03C0			ADD		AX,AX
076A:000A B8004C		MOV		AX,4C00
076A:000D CD21			INT		21
076A:000F 0000		  ADD		[BX+SI],AL
076A:0011 0000		  ADD		[BX+SI],AL
076A:0013 0000		  ADD		[BX+SI],AL
076A:0015 0000		  ADD		[BX+SI],AL
076A:0017 0000		  ADD		[BX+SI],AL
076A:0019 0000		  ADD		[BX+SI],AL
076A:001B 0000		  ADD		[BX+SI],AL
076A:001D 0000		  ADD		[BX+SI],AL
076A:001F 0000		  ADD		[BX+SI],AL

// 执行MOV AX,0123,结果AX=0123 IP=0003指向下一条指令
-t
AX=0123 BX=0000 CX=000F DX=0000 SP=0000 BP=0000 SI=0000 DI=0000
DS=075A ES=075A SS=0769 CS=076A IP=0003 NV UP EI PL NZ NA PO NC
076A:0003 BB5604		MOV		BX,0456

// 执行MOV BX,0456,结果BX=0456 IP=0006指向下一条指令
-t
AX=0123 BX=0456 CX=000F DX=0000 SP=0000 BP=0000 SI=0000 DI=0000
DS=075A ES=075A SS=0769 CS=076A IP=0006 NV UP EI PL NZ NA PO NC
076A:0006 03C3			ADD		AX,BX

// 执行ADD AX,BX,结果AX=0579 IP=0008指向下一条指令
-t
AX=0579 BX=0456 CX=000F DX=0000 SP=0000 BP=0000 SI=0000 DI=0000
DS=075A ES=075A SS=0769 CS=076A IP=0008 NV UP EI PL NZ NA PO NC
076A:0008 03C0			ADD		AX,AX

// 执行ADD AX,AX,结果AX=0AF2 IP=0006指向下一条指令
-t
AX=0579 BX=0456 CX=000F DX=0000 SP=0000 BP=0000 SI=0000 DI=0000
DS=075A ES=075A SS=0769 CS=076A IP=000A NV UP EI PL NZ NA PO NC
076A:000A B8004C		MOV		AX,4C00

// 执行MOV AX,4C00,结果AX=4C00 IP=0006指向下一条指令
-t
AX=4C00 BX=0456 CX=000F DX=0000 SP=0000 BP=0000 SI=0000 DI=0000
DS=075A ES=075A SS=0769 CS=076A IP=000D NV UP EI PL NZ NA PO NC
076A:000D CD21		INT		21

// 最后执行int 21,这里需要输入p
-p
Program terminated normally

debug和源程序数字的默认进制

  • 在debug中,默认所有数字都是 16 进制,加了 h 反而会报错;
  • 在汇编源程序 .asm 中,不加 h 则默认为 10 进制,加 h 才表示 16 进制,加 b 为后缀为二进制;
  • 使用 debug 跟踪可执行程序 .exe 的时候,debug会将不加 h 的 10 进制(或者加了b为后缀的二进制)变为对应的 16 进制。

4、DOS系统的shell

  • 操作系统是由多个功能模块组成的庞大、复杂的软件系统。任何通用的操作系统,都要提供一个称为shell(外壳)的程序,用户(操作人员)使用这个程序来操作计算机系统进行工作。
  • DOS中有一个程序command.com,这个程序在DOS中称为命令解释器,也就是DOS系统的shell。
  • DOS启动时,先完成其他重要的初始化工作,然后运行command.com,运行后执行完其他的相关任务后,在屏幕上显示出由当前盘符和当前路径组成的提示符,比如:"c:"或"c:\windows"等,然后等待用户的输入。
  • 用户可以输入所要执行的命令,比如,cd、dir、type等,这些些命令由command执行,command执行完这些命令后,再次显示由当前盘符和当前路径组成的提示符,等持用户的输入。
  • 如果用户要执行一个程序,则输入该程序的可执行文件的名称,command首先根据文件名找到可执行文件,然后将这个可执行文件中的程序加载入内存,设置CS:IP指向程序的入口。此后,command暂停运行,CPU运行程序。程序运行结束后,返回到command中,command再次显示由当前盘符和当前路径组成的提示符,等待用户的输入。
  • 在DOS中,command处理各种输入:命令或要执行的程序的文件名。我们就是通过command来进行工作的。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Selenium 自动化高级操作与解决疑难杂症,如无法连接、使用代理等

解决 Selenium 自动化中的常见疑难杂症 这里记录一些关于 Selenium的常用操作和疑难杂症。 有一些细节的知识点就不重复介绍了,因为之前的文章中都有! 如果对本文中的知识点有疑问的,可以先阅读我以前分享的文章! 知识点&…

【滑动窗口】LeetCode2953:统计完全子字符串

作者推荐 [二分查找]LeetCode2040:两个有序数组的第 K 小乘积 本题其它解法 【离散差分】LeetCode2953:统计完全子字符串 题目 给你一个字符串 word 和一个整数 k 。 如果 word 的一个子字符串 s 满足以下条件,我们称它是 完全字符串: s 中每个字符…

【UGUI】sprite精灵的创建与编辑

如何切图(sprite editor) 有时候一张图可能包含了很多张子图,就需要在Unity 临时处理一下,切开,比如动画序列帧图集 虽然我们可以在PS里面逐个切成一样的尺寸导出多张,再放回Unity,但是不需要这…

通讯录管理系统(基于C语言)

模块设计 本通讯录管理系统功能模块共包括9个部分:1.输入数据、2.显示数据、 3.插入数据、4.删除数据、5.查看数据、6.修改数据、7.保存数据、 8.返回主菜单、9.退出系统. 一.总体设计 通讯录的每一条信息包括:姓名、性别、住址、联系电话…

[leetcode ~二叉树] 模版

文章目录 1. 左叶子之和2. 翻转二叉树 E 1. 左叶子之和 :::details 给定二叉树的根节点 root ,返回所有左叶子之和。 示例 1: 输入: root [3,9,20,null,null,15,7] 输出: 24 解释: 在这个二叉树中,有两个左叶子,分别是 9 和 15&…

java生成邮件eml文件例子

提前导入javamail.jar 仓库地址 仓库服务 导入引用类方法 import javax.mail.Message; import javax.mail.Session; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import java.io.FileOutputStream; import java.util.Properties…

10、外观模式(Facade Pattern,不常用)

外观模式(Facade Pattern)也叫作门面模式,通过一个门面(Facade)向客户端提供一个访问系统的统一接口,客户端无须关心和知晓系统内部各子模块(系统)之间的复杂关系,其主要…

利用DateFormat、Date、Calendar等相关类,编程实现如下功能

(1)用户输入2个日期,第一个日期用整数形式输入,把输入的整数设置为日历对象1的年月日的值。第二个日期以字符串形式输入,形如“2022-10-25”,并设置为日历对象2的年月日的值。将2个日期以“xx年xx月xx日”的…

国际语音呼叫中心适用的行业有哪些?

国际语音呼叫中心的出现,使企业可以在全球范围内提供统一的客户支持,有效地解决客户服务、市场营销等国际性电话沟通问题,为企业提供了卓越的全球客户服务,确保客户在不同国家和地区之间获得一致的、高质量的支持。那么哪些行业适…

熬夜会秃头——beta冲刺Day5

这个作业属于哪个课程2301-计算机学院-软件工程社区-CSDN社区云这个作业要求在哪里团队作业—beta冲刺事后诸葛亮-CSDN社区这个作业的目标记录beta冲刺Day5团队名称熬夜会秃头团队置顶集合随笔链接熬夜会秃头——Beta冲刺置顶随笔-CSDN社区 一、团队成员会议总结 1、成员工作…

代码随想录刷题题Day5

刷题的第五天,希望自己能够不断坚持下去,迎来蜕变。😀😀😀 刷题语言:C / Python Day5 任务 ● 哈希表理论基础 ● 242.有效的字母异位词 ● 349. 两个数组的交集 ● 202. 快乐数 ● 1. 两数之和 1 哈希表理…

Db2的Activity event monitor在Db2 MPP V2上收集ROWS_INSERTED信息

注:本文不是讲解Db2 Activity event monitor,只是一个用法实践。要了解Activity event monitor,请参考 https://www.ibm.com/docs/en/db2/11.5?topicevents-activity-event-monitoring 。 环境 Red Hat Enterprise Linux release 8.8 (Oot…

“构建智慧城市,共享美好生活“2024杭州国际智慧城市展览会

智慧城市作为当今社会发展的必然趋势,正在被越来越多的企业和观众所关注。为了进一步推动智慧城市的发展,2024杭州智慧城市展览会将于4月份在杭州国际博览中心盛大召开。目前,招商工作已近半程,大批国内外知名企业踊跃报名&#x…

会话技术(Cookie与Session)

会话技术 一.作用域对象 1.作用域对象概述 有作用域的对象作用域对象可以用来存储数据并且可以在不同的组件之间进行传递传递的范围受作用域的限制,一旦超过范围,立即失效 2.两个作用域对象 作用域对象描述request对象作用范围是一次请求ServletCon…

3D Gaussian Splatting的使用

3D Gaussian Splatting的使用 1 下载与安装2 准备场景样本2.1 准备场景照片2.1.1 采集图片2.1.2 生成相机位姿 3 训练4 展示 1 下载与安装 今年SIGGRAPH最佳论文,学习了一下,果然厉害,具体论文原理就不说了,一搜都有,…

HOST文件被挟持,无法上网,如何解决。

问题: 晚上开机,突然发现无法联网,提示网络异常 解决: 首先网络诊断,host文件被劫持,修复后,仍然不行。 然后测试手机热点,发现仍然无法联网 尝试用火绒修复,无果。 所有…

安路Anlogic FPGA下载器的驱动安装教程

安路FPGA下载器驱动安装教程 安路FPGA下载器:EN-ALC10,是一款高性能FPGA下载线(编程器),支持安路的开发软件TDS和全系列FPGA芯片下载编程,支持全速USB2.0与电脑进行数据通信,通过JTAG协议与FPGA进行程序下…

【mysql】基于binlog数据恢复指令和坑

文章目录 1.binlog相关配置是否开启binlogbinlog日志格式 2.导出binlog日志mysqlbinlog指令updateinsertdeletebinlog中的事件 3.数据恢复4.特别注意的坑为什么bash脚本执行mysqlbinlog,无法找到指令为什么执行mysqlbinlog,无法数据恢复 1.binlog相关配置…

【杂】解决关于mean(0)理解错误引发的程序bug

一、环境和解释器要一起配置好 invalid syntax 发生你在终端激活了一个环境,但 VSCode 依然使用之前的解释器的情况。 解释器设置影响了 VSCode 中运行 Python 脚本、调试、代码补全等功能的行为。VSCode 会根据你选择的解释器来执行这些操作。 二、关于mean&#x…

【c】序列中整数去重

数组中的元素不好直接删除&#xff0c;我们可以把重复的数做标记&#xff0c;将他赋值为0&#xff0c;然后正常打印数组&#xff0c;为0的跳过 #include<stdio.h> int main() {int n;scanf("%d",&n);int arr[n1];for(int i1;i<n;i){scanf("%d&quo…