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 segmentmov ax,0123Hmov bx,0456Hadd ax,bxadd ax,axmov ax,4c00Hint 21Hcodemsg 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,4c00Hint 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 free0 Warning Errors0 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 free0 Warning Errors0 Server  ErrorsC:\>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:\>firstc:\>

完整过程

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来进行工作的。

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

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

相关文章

软件平台架构设计与技术管理之道笔记

软件平台架构设计与技术管理之道笔记 认知 领导软件平台各方面的工作,对技术底蕴、思维模式、决策能力、工作风格、文化铸造等方面都有极高的要求,可以称之为“领域智慧”。认知盲区的代价是巨大的,“不知”比“不会”的后果更严重&#xf…

探讨Unity中的动画融合技术(BlendTree)

动画在游戏和虚拟现实应用中扮演着关键的角色,而动画融合技术则是使角色动作更加流畅和逼真的核心。在Unity引擎中,我们可以使用动画混合树(Blend Trees)来实现这一目标。本篇技术博客将深入讨论动画融合技术的实现原理、在Unity中…

做一个类似万师傅家政小程序需要有哪些功能?

现如今人们生活节奏不断加快,自然很少有时间去处理生活中的琐事,恰好家政维修保洁小程序开发则能给线下用户提供方便。 家政保洁小程序应该具备哪些功能? 1、提供家政行业资讯,方便用户在选择家政保洁前了解行业动态。 2、分类搜…

Android wifi Enable之后扫描流程

流程框架图 通常我们在设备开启wifi之后,等会会自动扫描出周围的热点。 下面看下自动扫描周围热点的流程 代码流程 1. ClientModeManager.ClientModeStateMachine ClientModeStateMachine 由CMD_START 转换到StartedStateStartedState 状态机,在更新…

让代码变得优雅简洁的神器:Java8 Stream流式编程

原创/朱季谦 本文主要基于实际项目常用的Stream Api流式处理总结。 因笔者主要从事风控反欺诈相关工作,故而此文使用比较熟悉的三要素之一的【手机号】黑名单作代码案例说明。 我在项目当中,很早就开始使用Java 8的流特性进行开发了,但是一直…

流媒体方案之FFmpeg——实现物联网视频监控项目

目录 前言 一、FFmpeg介绍 二、FFmpeg简易理解 三、FFmpeg的重要概念 四、软硬件准备 五、移植、运行FFmpeg 六、运行FFmpeg 前言 最近想做一个安防相关的项目,所以跟着韦东山老师的视频来学习视频监控方案的相关知识,韦东山老师讲的课非常好&…

LaTex入门简明教程

文章目录 写在前面安装Texlive的安装TeXstudio 的安装 LaTex 的使用节指令图指令表指令公式指令参考文献指令引用指令TeXstudio 编译 LaTex 的 \label{} 写法建议最后 写在前面 这篇文章面向没有任何 LaTex 基础的小白,主要讲解了 LaTex 的安装和使用。读完文章之后…

android https 证书过期

有的时候 我们android https 证书过期 ,或者使用明文等方式去访问服务器 可能会碰到类似的 问题 : javax.net.ssl.SSLHandshakeException: Chain validation failed java.security.cert.CertPathValidatorException: Response is unreliable: its validi…

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

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

西南科技大学模拟电子技术实验七(集成运算放大器的非线性应用)预习报告

一、计算/设计过程 说明:本实验是验证性实验,计算预测验证结果。是设计性实验一定要从系统指标计算出元件参数过程,越详细越好。用公式输入法完成相关公式内容,不得贴手写图片。(注意:从抽象公式直接得出结果,不得分,页数可根据内容调整) 预习计算内容根据运放的非线…

【Linux下如何生成coredump文件】

一,什么是coredump 我们经常听到大家说到程序core掉了,需要定位解决,这里说的大部分是指对应程序由于各种异常或者bug导致在运行过程中异常退出或者中止,并且在满足一定条件下(这里为什么说需要满足一定的条件呢&#…

QT使用SQLite(打开db数据库以及对数据库进行增删改查)

QTSQLite 在QT中使用sqlite数据库,有多种使用方法,在这里我只提供几种简单,代码简短的方法,包括一些特殊字符处理。 用SQlite建立一个简单学生管理数据库 数据库中有两个表一个是class和student。 class表结构 student表结果…

非标设计之气缸类型

空压机: 空压机又称空气压缩机,简单来说就是将机械能转化为压力能来进行工作的,空压机在电力行业应用比较多,除了在电力行业应用较多外,其实空压机还有一个比较常见的用途就是用来制冷和分离气体,输送气体…

【web安全】RCE漏洞原理

前言 菜某的笔记总结,如有错误请指正。 RCE漏洞介绍 简而言之,就是代码中使用了可以把字符串当做代码执行的函数,但是又没有对用户的输入内容做到充分的过滤,导致可以被远程执行一些命令。 RCE漏洞的分类 RCE漏洞分为代码执行…

RT-Thread 三步实现利用DMA进行串口发送

应某些网友需求,说网上根本找不到基于Rt-Thread DMA串口发送代码,只有官方开源的串口DMA接收。 其实这些东西并不难,只要你细心去看哪些闲置的驱动文件且都是包装好的,通过关键字去查询或点开源文件查看,花不了几分钟…

【C/PTA —— 14.结构体1(课内实践)】

C/PTA —— 14.结构体1(课内实践) 6-1 计算两个复数之积6-2 结构体数组中查找指定编号人员6-3 综合成绩6-4 结构体数组按总分排序 6-1 计算两个复数之积 struct complex multiply(struct complex x, struct complex y) {struct complex product;product.…

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

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

PyQt实战 创建一个PyQt5项目

前后端分离 参考链接 PyQt5实战(二):创建一个PyQt5项目_pyqt5实战项目_笨鸟未必先飞的博客-CSDN博客 项目目录 创建一个QT项目 调用pyuic工具将dialog.ui文件编译为Python程序文件ui_dialog.py。 # -*- coding: utf-8 -*-# Form implemen…

【离散差分】LeetCode2953:统计完全子字符串

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

云原生之深入解析如何限制Kubernetes集群中文件描述符与线程数量

一、背景 linux 中为了防止进程恶意使用资源,系统使用 ulimit 来限制进程的资源使用情况(包括文件描述符,线程数,内存大小等)。同样地在容器化场景中,需要限制其系统资源的使用量。ulimit: docker 默认支持…