有关CPU和存储单元的概念在前一节我们已经了解,那么如何观察实际机器内部的情况呢?能不能看到具体的寄存器、标志、存储单元的内容呢?可不可以修改和控制它们呢?
DEBUG这个有力工具,就可以深入到机器内部进行观察了。
调试工具DEBUG
在DOS操作系统和Windows操作系统中,都提供了调试工具DEBUG。DEBUG是为汇编语言设计的一种调试工具。
1. DEBUG的主要命令
DEBUG命令有20多个,我们主要学习最常用的命令。
- R ——查看和修改寄存器
- D ——查看内存单元
- E ——修改内存单元
- U ——反汇编,将机器指令变为汇编指令
- T /P——单步执行
- G ——连续执行程序
- A ——输入汇编指令
- Q ——退出
2. 进入DOS
DEBUG要先进入DOS环境中再使用,linux虚拟环境中进入DOS的方法:
- 进入Linux的命令行终端
- 输入
DOSemu
进入DOS环境,DOSemu
也有其他参数,可以输入dosemu --help
查看 - 退出DOS环境,在DOS中输入命令
exitemu
- 或者在桌面上双击dosemu图标,直接进入DOS
基本的DOS命令:
- cd\ ——首先要用cd\ 退回到根目录C>下
- dir ——显示文件列表
- md hb ——建立hb子目录
- cd hb ——进入hb子目录
- copy d:\dos\masm.exe c:\hb ——将D盘dos目录下的masm.exe拷贝到C盘hb目录下
- copy d:\dos\link.exe c:\hb ——将D盘dos目录下的link.exe拷贝到C盘hb目录下
- cd .. ——退回到上一级目录
- del \hb\masm.exe ——删除hb子目录中的某文件
- rd hb ——删除hb子目录(子目录中的所有文件必须先删除)
- e:——进入e盘
- cls ——清屏
- type——显示文本文件内容(如type c:\hb\abc.asm)
DOS和DEBUG命令都支持大小写。
3. 进入DEBUG
要观察计算机内部的情况,可直接进入DEBUG。如果要调试及观察可执行文件,则要在DEBUG后加上文件名和扩展名.EXE。我们先观察,因此直接键入DEBUG
进入系统,如图所示。
DEBUG的提示符是小短线- ,在其后输入命令。
1. R命令——查看和修改寄存器
R命令有两种用法:直接键入R——将显示CPU所有的寄存器和标志位;
修改寄存器——在R后跟写寄存器名,回车后先显示寄存器的内容,在冒号后键入新的值;再用R命令就可看到修改后的内容了。将AX寄存器的值改为1234H。
再来看四个段寄存器DS、ES、SS、CS的值都是07BE,说明现在系统处在同一个逻辑段中(不同的系统环境下,段寄存器的值可能不一样)。操作系统根据内存的情况为各段分配段地址,因此每台机器或每次运行时段地址值可能会不一样。
IP指令指针寄存器的值是0100H,表示将要执行的指令在代码段的0100H单元中。该指令单元的逻辑地址应该由CS:IP构成,即0AFA:0100H。
我们来看在寄存器的下面那一行的表示。该行显示的是代码段的一条指令的反汇编。所谓反汇编,指的是将二进制的机器指令显示成汇编指令。由三部分构成:最左边07BE:0100表示该指令所在单元的逻辑地址,中间F60000表示该指令的机器码,第3列显示为汇编指令TEST。
2. D命令——查看内存单元
内存每16个字节单元为一小段,逻辑段必须从小段的首址开始。用D命令可以查看存储单元的地址和内容。
D命令格式为:
D 段地址:起始偏移地址 [结尾偏移地址] [L范围]
例如:
D DS:0 查看数据段,从0号单元开始 D ES:0 查看附加段,从0号单元开始 D DS:100 查看数据段,从100H号单元开始 D 0200:5 15 查看0200H段的5号单元到15H号单元(在虚拟机上该命令不能执行) D 0200:5 L 11 用L选择范围。查看0200H段的5号单元到15H号单元共10个单元
其中左边一列为逻辑地址,中间部分为存储单元的内容。每行为16个字节单元,中间的小横线用于区分前8个单元和后8个单元。在逻辑地址中只给出每行第一个单元的偏移地址,其余15个单元的偏移地址没有标出。可以推断出图中第一行单元的偏移地址从0000H到000FH,第二行单元的偏移地址为0010H~001FH,以此类推。右边部分显示出内存单元中的ASCII码表示的字符,无法显示时用小点代替。
如果在D后面直接写出偏移地址,则显示当前数据段下偏移地址开始的内存单元,如:
D 10 从数据段10H号单元开始显示
D100 从数据段100H号单元开始显示
注意:多次键入D,可连续显示后面的单元内容。
3. E命令——修改内存单元
用E命令可以改写多个存储单元的内容。格式为:E 起始地址 修改值 修改值 …
例如:将数据段中的DS:3~DS:5 三个单元的内容修改为14、15、16。命令为
E DS:3 14 15 16
如果E后面直接跟偏移地址,则修改当前数据段下偏移地址所指单元值;还可以用E命令修改其它段的存储单元内容。
E 10 修改当前数据段10H号单元内容 E ES:100 修改附加段100H号单元内容 D ES:100 查看一下100H单元的内容是否修改了
4. A 命令——输入汇编指令
输入汇编指令,系统自动地将键入的汇编指令翻译成机器代码,并相继地存放在从指定地址开始的存储区中。由于DEBUG下的数值默认为十六进制数,因此先要将十进制数转换成十六进制数。
例如,前一节提到的计算Z=35+27的汇编指令为:
MOV AX,23H
ADD AX,1BH
MOV [0000],AX
输入A命令后,系统自动地给出逻辑地址为0AEE:0100(CS:偏移地址),在其后输入汇编指令,回车后可输入下一条指令,直接回车则退出输入。操作过程如下:
也可以在A命令后给出指令的存放地址,如A CS:0000,表示从代码段的0号单元开始存放输入的指令。
5. U命令 ——反汇编
程序员编写的汇编语言源程序经过汇编(编译)后生成了二进制的机器指令代码,而U命令可将二进制的机器指令变为助记符形式的汇编指令,因此称之为“反汇编”。
通过U命令,我们可以得到机器指令与汇编指令的对照,了解机器指令的存储情况
第一列为逻辑地址,第二列为机器指令,第三列为汇编指令
注意:上图显示的程序代码并不是用户编写的程序,因为在输入DEBUG命令时没有附加exe文件。这段程序代码是系统代码段中保存的内容,有可能是系统程序,也有可能是无效的代码。
U后跟偏移地址,则从该地址开始反汇编。如:
U 0 从代码段0号单元开始反汇编
U100 从代码段100H号单元开始反汇编
注意:多次键入U,可连续显示后面的程序部分。
6. T/P命令——单步执行
输入完指令后,应该执行它。
T命令可以一条一条地执行指令,相当于逐过程调试。
P命令的作用与T命令相同,当遇到中断指令INT n和调用指令CALL时,会进入子程序,相当于逐语句调试。
下面执行第四步中的汇编指令:
本次执行前,先用R命令查看指令指针寄存器IP的值是否为0100,如果不是,用R IP命令修改为0100。表示现在要从CS:0100单元开始执行指令。
T命令每执行一次,都会显示当前寄存器的状况,我们可以随时了解指令的执行情况。
用D DS:0命令查看该单元的值已经为003B(两个字节单元为一个字单元),这里类似大端法,高位在高地址,低位在低地址。
T命令还可以连续执行多条指令。如上例中连续执行3条指令,可用如下T命令:
-T 3
T命令也可以设置开始地址和执行条数。如上例中从0100H开始连续执行3条指令,可用如下T命令:
-T =0100 3
7. G命令——连续执行程序
8. Q命令 ——退出DEBUG
键入Q,回车后退出DEBUG,返回到DOS下。