引言
上篇博文中我们提到了CPU中四个段寄存器:CS,DS,SS,ES,这四个段寄存器只对CS做了详细讲述,以及CS和IP的指向含义和如何修改。那么剩下的DS,SS,ES这三个段寄存器都有什么用法,又会有什么样的使用呢?在接下来的博文中,我们就来好好的聊一聊,不过正所谓兵马未动,粮草先行,我们要先学习一个工具。
Debug
在开始学习之前,我们要先学习并认识一个很重要的工具:Debug。
什么是Debug
Debug是DOS、Windows都提供的实模式(8086 方式)程序的调试工具,使用它可以查看CPU各种寄存器的内容、内存的情况和在机器码级层跟踪程序的运行状态。
首先需要说明的是,Debug运行是在16位操作系统,在目前的Windows10中已经不存在Debug程序,所以我们需要搭建可供Debug的运行环境。
Windows10 Debug环境搭建
环境搭建过程比较简单,首先我们需要下载一个DOS的模拟程序:DOSBox。点击进入官网进行下载:
点击“Downloads”:
点击绿色按钮“Download Now” 即可开启下载。
下载完成后:
点击运行:
选择“Next”
继续“Next”
这里选择一个安装路径,博主选择的是D盘下新建的“DOSBoxStudy” 文件夹,点击“Install”:
出现“Completed”说明已经完毕,点击“Close”关闭窗口即可。 我们打开安装目录,如下:
直接点击“DOSBox.exe”运行DOSBox程序,这时候会弹出两个窗口:
对比两个窗口,第一个窗口是DOSBox状态窗口,我们不需要关注,第二个窗口才是DOXBox模拟的DOS窗口,是我们真正操作的输入指令的地方。观察这个窗口你会发现,首先它的右边是没有滚动条的,也就是说它的页面不可以鼠标操作滚动。这里其实有点坑,无法滚动页面也就意味着我们能够看到的信息就比较有限。另外这个窗口是比较小的,而且无法使用鼠标进行拉伸,只能通过修改DOSBox的配置文件,才能使窗口变大。
具体调整DOSBox窗口大小教程,请看这篇博文:调整DOSBox窗口大小,这位博主讲的比较详细和准确。
现在我们还需要下载Debug程序,这里博主贴上一个资源连接:Debug.exe下载资源
下载完成后是一个压缩包,如图所示:
将里面的debug.exe加压出来放到我们刚才创建的DOSBoxStudy文件夹下:
打开我们的DOSBox程序,在模拟界面输入指令:
mount c d:\DOSBoxStudy\
这是挂载指令,也就是说将d:\DOSBoxStudy\目录挂载到模拟DOS的C盘下,出现“Drive C is mounted as local directory d:\DOSBoxStudy\ ”表示挂载成功,挂载目的是为了可以访问我们本地路径d:\DOSBoxStudy\下的文件,因为我们需要运行该目录下的debug.exe程序。
挂在成功后,当前路径是Z盘,所以我们需要把路径切到C盘,输入:
C:
切到C盘路径后,我们就可以执行debug.exe程序,输入:
debug
出现“-”就表明此时已经进入debug程序成功运行,这时输入的命令则是debug程序里面的相关命令。
到这里就意味着我们已经完成了Debug.exe程序的环境安装以及运行,是不是非常的简单?如果你觉得每次打开DOSBox程序都需要重新挂载目录比较繁琐和麻烦,那么你可以去配置系统的环境变量,这样就不用每次都手动挂载了。具体教程你可以百度搜索,这里博主图省事就不想配置了。
Debug命令
Debug有20多个命令,我们最常用的有以下六个:
- R命令:用来查看、改变CPU寄存器中的内容
- D命令:用来查看内存中的内容
- E命令:用来改写内存中的内容
- U命令:将内存中的机器指令翻译成汇编指令
- T命令:执行一条机器指令,即单步调试
- A指令:以汇编指令的格式在内存中写入一条机器指令
下面我们就来详细说明一下上述六个命令
R命令
进入debug程序,我们输入r之后,界面如下:
首先我们能详细的看到各个寄存器中的值,比如AX寄存器,值为:0000H,BX寄存器值为:0000H。还有段寄存器,CS值为:073FH,DS值也是为:073FH。
我们看到IP值为:0100H,那么就意味着CPU接下来要执行073F:100地址处的代码。
我们观察到还有好些我们没见过的寄存器,比如:SP,BP,SI,DI,这些寄存器我们后面会逐一讲述到,这里就先不谈。
我们看最下面一行的内容:
073F:0100 0000 ADD [BX+SI],AL DS:0000=CD
这部部分内容展示的是接下来要执行的指令内容相关信息。
开头“073F:0100”表示指令的内存地址,“0000”表示这句指令的机器码,“ADD [BX+SI],AL”则是机器码对应的汇编语句,最后面“ DS:0000=CD”则表示将要执行的操作,这里我们还不熟悉所以不做详细解释。
我们还会注意到:
这是标志寄存器中的状态值,后面我们会学习到,这里先不做阐述。
下面我们说一下R命令的修改寄存器内容功能,需要给出具体修改的某个寄存器名,格式如下:
r 寄存器名
下面我们修改AX寄存器值,输入:r ax
执行后会打印出当前AX值,然后提示你输入新的值,我们输入1:
执行完成后,我们再使用R命令查看下当前,寄存器值,发现AX值确实被修改为1。
D命令
d命令功能是查看内存内容,所以在使用d命令时需要给出具体的需要查看的内存范围,格式为:
d 起始地址 结束地址
例如,我要查看073F:100~073F:10f,共十六个字节的数据,则输入:d 073f:100 10f:
执行后会在下面展示出指定范围的内存内容。
最后面“................”,其实是显示的是字节对应的ASCALL码,因为073F:100~073F:10f这十六个字节都是0,我们根据ASCALL表得知0对应的ASCALL码是“空字符”,所以显示是.......,表示空。
注意点1:
查看内存范围是我们决定,比如,我们可以查看073F:100~073F:11f,共32个字节,则输入:d 073f:100 11f
执行后就会显示两行内存内容。也就是说你想查看多大范围的内存内容就写上多大的范围即可。
这次我们发现最后面显示出“4”,这里是073f:11c处的字节为34H,34H对应的ASCALL码为字符4,所以显示出了“4”。
注意点2:
结束地址要大于起始地址,否则就会报错。例如输入命令:d 073f:100 ff,则报错:
因为ffH小于 100H,范围错误。
E命令
E命令功能是修改内存内容,所以它需要给出指定修改的内存内容的地址。格式为:
e 起始地址 数据 数据 数据 数据 .......
例如我要修改073F:100~073F:107范围8个字节的内容,改成1,2,3,4,5,6,7,8,则命令如下:
e 073f:100 1 2 3 4 5 6 7 8
如图所示:
如果没有出现错误提示,则说明修改成功,下面使用D命令查看下内存内容,来确定是否修改成功:
查看发现前八个字节内容确实被修改成了“1,2,3,4,5,6,7,8”,之前我们查看的内容都是0。
注意点:
你想修改多少个内存单元内容,你在后面就写多少个数据,使用空格隔开。每一个数据对应一个内存单元,随数据个数并逐渐递增。
例如上面的E命令中,起始地址为073f:100,我们想修改以此开始的8个字节,则写上“1 2 3 4 5 6 7 8”,其中1对应的偏移地址为100,2对应的偏移地址为101,3则对应102,以此递增,8对应的偏移地址为107。
如果我们要修改起始地址为073f:100的16个字节,则后面要写上16个数据。
U命令和A命令
这两个命令实际上是相互对应的,一个是把机器码翻译成汇编指令,一个是把汇编指令转译为机器码。我们先说A命令:以汇编指令的格式在内存中写入一条机器指令,所以我们需要指明需要写入的内存地址,格式为:
a 起始地址
如图,我们向073f:11f处写入汇编指令:输入:a 073f:11f
执行后会提示你在073f:11f处输入汇编指令,我们输入,mov ax,2
执行完成后我们会发现偏移地址变了,自动加上了“mov ax,2”这条指令对应机器码的长度,也就是11FH+3 = 122H。接下来就提示你继续输入地址073f:122处的汇编指令,如果你不想继续输入,则按“Enter”键即可退出输入。这里我们停止输入下条指令。
现在我们使用U命令来查看刚才我们输入的那条汇编指令,U命令功能是将内存中的机器码翻译成汇编代码,所以我们需要给出待翻译内存的起始地址和结束地址,格式为:
u 起始地址 结束地址
如图所示,我们输入:u 073f:11f 12f,查看这16个字节内容翻译成的汇编指令:
U命令的展示共有三个部分,从左向右开始,首先是内存地址,后面是机器码,最后是翻译成的汇编指令。我们能得到的信息为这条汇编指令的长度和汇编指令所在的地址。
从显示中我们可以看出,我们使用A命令确实向内存地址073f:11f处写入了汇编指令:mov ax,2,该指令共占3个字节。
T命令
T命令在接下来我们的汇编开发学习中是使用到最多的一个命令,它的功能是执行一条机器指令,也就是我们平时开发中最为熟知的单步调试。
T命令不需要输入额外的参数,所以直接输入t即可,但是要注意CS:IP的指向,是否为你需要执行的那段代码地址。
现在我们使用T命令去执行一下刚才我们向内存地址073f:11f处写入的汇编指令:mov ax,2:
首先我们需要将CS:IP指向改为073f:11f,我们使用R命令修改CS寄存器和IP寄存器地址,先改CS,输入:r cs:
发现CS值已经是073f,则不再修改,按“Enter”键退出输入。下面我们修改IP值,输入:r ip:
输入新的值:11f。下面我们再使用R命令查看下当前寄存器值是否已经修改,输入:r
我们发现IP值确实已经改为11f,而且我们发现下面已经显示接下来执行的指令就是:mov ax,2,证明我们已经把CS:IP指向了我们写入的那个地址。
接下来我们就可以使用T命令去执行,输入:t
我们发现执行后,AX寄存器的值变成了2,说明我们的指令成功执行。T命令执行完成后会再次输出当前各个寄存器的值以及状态,方便我们程序员动态跟踪寄存器状态。
本篇结束语
本篇博文中我们详细讲述了Debug.exe这个工具程序的环境搭建,以及它最主要的六个命令。针对Debug六个命令的功能和使用方法进行了细致讲述。Debug本身的使用其实并不是很难,希望小伙伴们能好好学习并掌握Debug的操作,因为接下来的学习中我们将会来不开Debug的使用。
下篇博文我们将讲述内存访问相关,涉及到段寄存器DS,SS的功能和作用。
感谢围观,转发分享请标明出处,谢谢!