使用debug
可以完成以下功能:
- 可以查看 和改变 CPU 中,寄存器的内容;
- 可以查看 和改变内存中的内容;
- 可以将内存中的 机器指令 翻译成汇编指令
- 使用汇编指令 在 内存中 存入 机器指令
- 执行机器指令
首先,启动 Debug
,在DOS提示符下输入命令:debug
-
debug 中,不区分大小写
; -
注意,DEBUG 下的数据都是十六进制数
。 -
查看内存地址时, 当输入的地址数据不足 4位时, 默认是从高位开始补零的;
1. 寄存器中的数据
1.1 查看寄存器中的内容
直接键入 R —— 将显示 CPU 所有的寄存器和标志位;
观察下图可知:
四个段寄存器 DS、ES、SS、CS 的值都是 0740H,说明现在系统处在同一个逻辑段中(不同的系统环境下,段寄存器的值可能不一样,dosemu 虚拟机中为 07BEH)。
-
操作系统根据内存的情况为各段分配段地址,因此每台机器或每次运行时段地址值可能会不一样。
-
IP 指令指针寄存器的值是 0100H,表示将要执行的指令在代码段的 0100H 单元中。
-
该指令单元的逻辑地址应该由 CS:IP 构成,即 0740:0100H。
1.2 修改寄存器中的内容
- 在 R 后跟写寄存器名(比如 R AX),
- 回车后先显示寄存器的内容,
- 在冒号后键入新的值;
注意,DEBUG 下的数据都是十六进制数
。
再用 R 命令就可看到修改后的内容了。
2. 内存中的数据
2.2 查看内存中的内容
- D - 列出预设地址内存处的128个字节的内容
注意, 最开始列出的 内存的 地址处, 默认是从 cs: ip 所指向的 内存地址,
即当前 需要执行指令的 开始处 ;
-
D 段地址:偏移地址 - 列出内存中指定地址处的内容
-
D 段地址:偏移地址 结尾偏移地址 代表: 列出内存中指定地址范围内的内容
2.3 修改内存中的内容
按照顺序 逐个修改的方式,
- E 段地址:偏移地址 数据1 数据2 …
另外一种逐个修改的方式, 适用于指定内存单元处的修改:
- E 段地址:偏移地址
- 逐个询问式修改
- 空格 - 接受,继续
- 回车 - 结束
3. 返回汇编: 机器指令翻译成汇编指令
首先将以下 机器指令写入到 内存单元中的 cs: ip 开始的地方:
:对应的机器码为
B8 23 01
BB 03 00
89 D8
01 D8
查看 内存中 写入结果,如上图所示
3.1 机器码 对应的汇编指令
然后, 用u命令可以查看内存中机器指令所对应的汇编指令。
:有汇编指令
mov ax, 0123H
mov bx, 0003H
mov ax, bx
add ax, bx
U 后跟偏移地址,则从该地址开始反汇编。如:
U 0 从代码段0号单元开始反汇编
U100 从代码段100H号单元开始反汇编
3.2 机器指令与汇编指令的对应关系
注意, 用 r
命令查看 时,
最后一行, 显示的 cs:ip 当前 cpu 将要执行的下一个指令, 该指令的地址, 对应的机器码, 以及对应的汇编指令;
我们来看在寄存器的下面那一行的表示。该行显示的是代码段的一条指令的反汇编。
-
所谓反汇编,指的是将二进制的机器指令显示成汇编指令。
-
由三部分构成:最左边 07BE:0100 表示该指令所在单元的逻辑地址,中间 F60000 表示该指令的机器码,第 3 列显示为汇编指令 TEST BYTEPTR [BX+SI],00,该指令为 TEST 测试指令。
通过 DEBUG,我们就可知道一条汇编指令翻译成机器代码是什么值了;反之也一样,对一条机器指令也可得知它代表什么汇编指令。
如图中的, 标志寄存器的最高位 是 溢出标志, 此时的状态是 NV
,代表此时值为0;
在图的最右边显示的是 CPU 标志寄存器各标志位的状态,可对照表 2-1 观察一下现在系统的状态。
4. 汇编指令写入内存中
用A命令以汇编指令的格式在内存中写入机器指令;
回车后可输入下一条指令,直接回车则退出输入。
:有汇编指令
mov ax, 0123H
mov bx, 0003H
mov ax, bx
add ax, bx
注意, 用 r
命令查看 时,
最后一行, 显示的 cs:ip 当前 cpu 将要执行的下一个指令, 该指令的地址, 对应的机器码, 以及对应的汇编指令;
:对应的机器码为
B8 23 01
BB 03 00
89 D8
01 D8
5. 执行指令
5.1 t 执行指令
用T命令执行机器指令;
T 命令每执行一次,都要显示当前寄存器的状况,我们可以随时了解指令的执行情况。
T 命令还可以连续执行多条指令。如上例中连续执行 3 条指令,可用如下 T 命令:
-T 3
T 命令也可以设置开始地址和执行条数。如上例中从 0100H 开始连续执行 3 条指令,可用如下 T 命令:
-T =0100 3
5.2 p 执行指令
P 命令的作用与 T 命令相同,当遇到中断指令 INT n
和调用指令CALL
时,应该使用 P 命令,以确保程序正常执行。这是因为INT n
指令和 CALL
指令都要转移到子程序去执行,T 命令进入子程序后可能无法返回;而 P 命令则直接执行该指令,并将结果带回。遇到循环指令 LOOP 时也应该使用 P 命令,可以使循环快速结束。
5.3 G 命令——连续执行程序
有关连续执行命令 G 的用法我们放到后面章节中学习
q - 退出Debug
6. 小结
在 DOS 操作系统和 Windows 操作系统中,都提供了调试工具 DEBUG。
DEBUG 是为汇编语言设计的一种调试工具,它通过单步、设置断点等方式为程序员提供了非常有效的调试手段。利用它可以观察和修改 CPU 的寄存器、内存单元;可以跟踪程序的运行,发现程序的错误。
实验楼环境中采用 dosemu 来模拟 DOS 环境,进入 DOS 环境中可以直接启动 DEBUG 程序。
DEBUG 命令有 20 多个,我们主要学习最常用的命令。
注意:DOS 和 DEBUG 命令都支持不区分大小写。
R ——查看和修改寄存器
D ——查看内存单元
E ——修改内存单元
U ——反汇编,将机器指令变为汇编指令
T / P ——单步执行
G ——连续执行程序
A ——输入汇编指令
Q ——退出
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)
6.2 内容解释
其中左边一列为逻辑地址,中间部分为存储单元的内容。
每行为 16 个字节单元,中间的小横线用于区分前 8 个单元和后 8 个单元。在逻辑地址中只给出每行第一个单元的偏移地址,其余 15 个单元的偏移地址没有标出。可以推断出图中第一行单元的偏移地址从 0000H 到 000FH,第二行单元的偏移地址为 0010H~001FH,以此类推。右边部分显示出内存单元中的 ASCII 码表示的字符,无法显示时用小点代替。
-
图中第一条 D 命令:
d ds:0
显示的是数据段存储单元的内容,可以看到数据段的段地址为 DS,其值 0B05H。0 号单元的内容为 CDH,1 号单元为 20H ,…,第 15 号单元的内容为 03H;第二行 0010H 号(16 号)单元的内容为 69H,它是小写字母 i 的 ASCII 码,因此右边区域中显示了 i ,表示该单元的值 69H 可以看成 ASCII 码。
-
第二条 D 命令:
d 0200:0
显示 0200H 段中的内容,也是从 0 号单元开始。 -
第三条 D 命令:
d 0200:5 15
从 0200H 段的 5 号单元开始显示直到 15H 号单元。
如果在 D 后面直接写出偏移地址,则显示当前数据段下偏移地址开始的内存单元,如:
D 10 从数据段10H号单元开始显示
D100 从数据段100H号单元开始显示
注意:多次键入 D,可连续显示后面的单元内容。