DEBUG是基于命令行的16位调试器,可作为16位汇编语言程序的调试工具,但不支持32位指令。
一.进入DEBUG
a.开始--运行--cmd--回车--debug--回车
b.开始--程序--附件--命令提示符--回车--debug--回车
c.开始--运行--command--回车--debug
DEBUG对应的可执行文件为debug.exe。启动DEBUG的命令格式为:
DEBUG[<可执行文件路径名>[<参数表>]]
其中,<可执行文件路径名>是要调试的可执行文件名(.exe或.com文件),扩展名不能省略。<参数表>是被调试程序所需的命令行参数。例如,键入命令
DEBUG demo.exe
将进入DEBUG,同时将指定的程序demo.exe装入内存,以便调试。
若启动DEBUG时未给出文件名,则仅运行DEBUG。需要时,可用N和L命令装入被调试程序。
进入DEBUG后,出现提示符“-”。若启动DEBUG时给出文件名,则BX:CX包含被调试文件的字节数。在DEBUG提示符下,可使用DEBUG命令。
二.DEBUG命令格式
DEBUG的每个命令都是一个字母,后跟一个或多个参数。下面对DEBUG命令作几点说明。
.字母不分大小写。
.只使用16进制数,且不能带后缀H。
.以空格或逗号作为命令各项之间的分隔符。分隔符只在两个数值之间是必须的。
.可以用Ctrl-C或Ctrl-Break终止命令的执行。
.若输入的命令有语法错误,则提示“Error”,并用“^”指出错误位置。
三.DEBUG命令的参数
在DEBUG中,许多命令的参数是〈地址〉和〈地址范围〉。〈地址〉的格式包括下列两种:
.〈段地址〉:〈偏移地址〉;
.〈偏移地址〉。
其中,〈段地址〉可以是数值或段寄存器,〈偏移地址〉是数值。若未指定〈段地址〉,则采用命令的缺省值。与数据有关的命令D、E、C和F等,缺省段地址为DS的值;与代码有关的命令A、U、G、T和P等,缺省段地址为CS的值。例如:
2000:1000;段地址为2000H,偏移地址为1000H
DS:2000 ;段地址为DS的值,偏移地址为200H
200 ;段地址为所在命令的缺省值(CS或DS),偏移地址为200H
〈地址范围〉用来表示一个内存区域,包括下列两种格式:
.〈开始地址〉〈结束地址〉;
.〈开始地址〉L〈长度〉。
其中,〈结束地址〉不能带段地址,〈长度〉表示字节数,且指定的地址范围不跨段。例如,内存区域2000:1000H到2000:1010H可表示为
2000:1000 1010
或
2000:1000 L 11
四.DEBUG命令
在DEBUG提示符下,使用帮助命令“?”,可以显示DEBUG命令列表。在众多DEBUG命令中,较常用的命令是U、D、E、R、G、T、P和Q。
1.内存显示命令(Dump Command)
D命令用来显示内存单元的值,包括下列两种格式:
(1)D[<地址>]
显示由指定地址开始的若干内存单元值。对于80列显示模式,显示128个字节。如果未指定参数,则按一个D命令的结束地址开始显示。若前面未用过D命令,则缺省从CS:IP开始显示。
(2)D<地址范围>
该命令显示由<地址范围>指定的所有内存单元的值。
执行D命令后,屏幕左边显示的是内存地址,中间是从该地址开始的若干字节值(十六进制),右边是每个字节对应的ASCII字符,其中,“.”表示不可打印字符。
若只给出偏移地址,则使用DS当前值作为段地址。例如:
D 2000:100 ;显示从2000:0100H开始的内存单元值
D 100 ;显示从DS:100H开始的内存单元值
D CS:100 ;显示从CS:100H开始的内存单元值
D ;显示从CS:IP开始的内存单元的值
2.内存修改命令E(Enter Command)
E命令用来设置指定内存单元的值,包括下列两种格式:
(1)E<地址>;
(2)E<地址><字节表>。
若只给出偏移地址,则使用DS当前值作为段地址。
第一种格式以交互方式逐个修改连续的内存单元。键入该命令后,DEBUG显示指定地址及相应内存单元的值,等待用户修改。此时,可以采用下列操作:
.输入一个新的值;
.键入空格跳到下一个地址单元;
.输入“_”返回上一个地址单元;
.按回车键结束E命令。
第二种格式用<字节表>来修改从指定地址开始的内存区域。DEBUG将这些值依次写入开始于指定地址的连续内存单元。其中,<字节表>是以空格或逗号分隔的若干十六进制字节或字符串。例如:
E 0 1'123'0A ;将内存单元DS:0--DS:4的值设置为01H、31H、32H、33H、0AH
注意:E命令后必须指定内存地址
3.寄存器命令R(Register Command)
R命令用来显示和修改寄存器的值,包括以下两种格式。
(1)R
显示所有寄存器和8个标志位的值,并反汇编CS:IP所指的指令。
(2)R<寄存器名>
显示指定寄存器的值,并等待用户键入新的值,按回车键结束R命令。其中,<寄存器名>只能是8086的16位寄存器AX、BX、CX、DX、SP、BP、SI、DI、DS、ES、SS、CS、IP与F(标志寄存器)。
显示的8个标志位的符号分别为(0/1):OF=NV/OV,DF=UP/DN,IF=DI/EI,SF=PL/NG,ZF=NZ/ZR,AF=NA/AC,PF=PO/PE,CF=NC/CY。例如,命令
R F
将显示8个标志位的值,然后等待用户修改。只要输入这些符号就可以设置对应标志位的值,键入符号的个数与顺序可以任意。
4.汇编命令A(Assemble Command)
命令的格式为:
A[<地址>]
该命令的功能是将用户输入的汇编语言指令汇编为机器代码,存入指定地址开始的内存单元。
若只给出偏移地址,则使用CS当前值作为段地址。若未指定地址,则从一个A命令的最后一个单元开始;若前面未用过A命令,则缺省为CS:IP。
当执行A命令时,DEBUG等待用户输入指令序列。输入每条指令后回车,再直接按回车键结束A命令。DEBUG将输入指令序列的机器码存入指定地址开始的内存单元中。
使用A命令时,要注意以下几点。
.远返回的助记符为RETF。
.除了汇编语言指令外,还可以使用伪指定DB和DW,将字节或字送入相应的内存单元。然而,DB和DW后不能使用“?”、表达式或DUP子句等。
.不能使用符号地址。
.为了区分立即数与内存操作数,地址必须放在方括号([])中。例如:
MOV AX,1234 ;立即数送AX
MOV AX,[1234] ;内存单元的值数送AX
.段超越前缀要在相关指令前或单独一行输入。例如,指令
MOV AX,ES:[100H]
在DEBUG中的正确形式为:
ES:MOV AX,[100]
或者
ES:
MOV AX,[100]
5.反汇编指令U(Unassemble Command)
U命令用来将二进制代码反汇编为汇编语言的符号指令,包括下列两种格式。
(1)U[<地址>]
从指定地址开始,反汇编若干字节。对于80列模式,反汇编32个字节(为了保证最后一条指令的完整性,可能会多于32个字节)。若未指定地址,则从上一个U命令的最后一个单元开始;若前面未用过U命令,则缺省为CS:IP。
(2)U[<地址范围>]
对指定范围的内存区进行反汇编。若只给出偏移地址,则使用CS当前值作为段地址。
执行U命令后,屏幕左边显示的是内存地址,中间是机器代码,右边是对应的汇编语言指令。
6.运行命令G(Go Command)
G命令的格式为:
G[=<地址>][<断点地址1><断点地址2>...<断点地址10>]
其中,等号“=”后的<地址>指出程序执行的饿起始地址,如未指定,则缺省为CS:IP。指定的断点最多为10个,也可以没有。若只给出偏移地址,则使用CS当前值作为段地址。
G命令从指定地址开始执行内存中的程序,直到程序结束或遇到指定的任一断点时停止执行。若遇到断点,则显示所有寄存器和标志位的当前值以及要执行的下一条指令;若程序正常结束,则显示“Program terminated normally”。
说明:
.断点地址的次序是任意的。设置多个断点的好处在于当被调试程序有多条可能的执行路径时,使其不管沿哪个路径执行,都有可能在断点处停下来,以便检查程序的执行情况。
.断点一经设定,DEBUG用一条INT3指令取代断点处指令的操作码。当程序执行到一个断点地址时,立即停止,然后恢复所有断点处的指令,并取消全部断点,返回DEBUG。如果设置的断点在G命令的执行过程中均未遇到,则程序执行完毕,不会恢复断点处的指令。
.一旦程序执行完毕,若想再次执行,必须重新装入。
.对于G以及下面介绍的T与P命令,等号“=”后的<地址>所指单元,必须是有效的8086指令代码,否则,会产生预想不到的结果。
7.跟踪命令T(Trace Command)
T命令的格式为:
T [=<地址>][<指令条数>]
其中,等号“=”后的<地址>指出程序执行的起始地址,如未指定,则缺省为CS:IP。若只给出偏移地址,则使用CS当前值作为段地址。
T命令从指定地址开始单步执行,执行的指令数有<指令条数>决定。每条指令执行后,都要显示所有寄存器和标志位的值以及下一条指令。若未给出<指令条数>,则缺省为1。
T命令执行时,若遇到CALL或INT指令,会跟踪进入相应过程或中断服务程序内部。对于带重复前缀(如REP)的指令,每次重复执行算一步。
8.继续命令P(Proceed Command)
P命令的格式为:
P [=<地址>][<指令条数>]
P命令类似于T命令,但将CALL、INT或带重复前缀(如REP)指令的执行当作一步,不会跟踪进入相应过程或中断服务程序内部。
9.退出命令Q(Quit Command)
Q命令的格式为:
Q
使用此命令可退出DEBUG。
10.内存比较命令C(Compare Command)
C命令用来比较两个内存块的值,格式如下:
C<地址范围><地址>
其中,<地址范围>指出第一个内存块,<地址>指出第二个内存块的起始地址。比较的字节数由<地址范围>确定。若只给出偏移地址,则使用DS当前值作为段地址。
C命令依次比较两个内存块的每个字节。若两块相等,则不输出任何信息;若发现有不相等的字节,则显示出它们的地址和值。屏幕从左到右的依次是:第一个内存块地址与相应的值、第二个内存块的值及其地址。例如:
C 2000:0 100 80 ;比较内存块2000:0H--2000:100H与DS:80H--DS:180H
C 2000:0 L 20 3000:0 ;比较内存块2000:0H--2000:1FH与3000:0H--3000:1FH
11.内存填充命令F(Fill Command)
F命令的格式为:
F<地址范围><字节表>
用此命令可将<字节表>中的字节写入<地址范围>所指定的内存区域。若只给出偏移地址,则使用DS当前值作为段地址。
若<字节表>中的字节数超过<地址范围>的字节数,则忽略多余的字节;若<字节表>中的字节数少,则重复使用这些数据,直到填满指定的<地址范围>为止。例如:
F 2000:0 7 0 ;将2000:0000H--2000:0007H的8个字节均置为0
F 0 7 1 2 3 ;将DS:0000H--DS:0007H的8个字节依次置为1、2、3、1、2、3、1、2
12.内存传送命令M(Move Command)
M命令用来将一个内存区的数据(或代码)复制到另一个内存区。格式如下:
M<地址范围><地址>
其中,<地址范围>指出要复制的源内存块,<地址>作为目的内存块的起始地址,复制的字节数由<地址范围>确定。若只给出偏移地址,则使用DS当前值作为段地址。
例如:
M 2000:0 100 80 ;复制内存块2000:0H--2000:100H的值到DS:80H--DS:180H
M 2000:0 L 20 3000:0 ;复制内存块2000:0H--2000:1FH的值到3000:0H--3000:1FH
如果源块与目的块重叠,DEBUG也能正确处理。
13.搜索命令S(Search Command)
S命令用来在指定的内存区域内搜索特定字节串。格式如下:
S<地址范围><字节表>
若只给出偏移地址,则使用DS当前值作为段地址。若未找到所需的字节串,则不显示任何信息;否则,显示其每次出现的地址。
14.十六进制数计算命令H(Hex Command)
H命令的格式为:
H<数值1><数值2>
计算两个十六进制(16位)的和与差。
15.文件命名命令N(Name Command)
N命令的格式为:
N[驱动器][路径]文件名[.扩展名]
此命令将指定的文件路径名存入DEBUG的文件控制块FCB中,以便后面用L或W命令把文件装入或存盘。<参数表>给出可执行文件运行时的命令行参数。例如,下列命令
DEBUG ;启动DEBUG
N Filename
L
相当于
DEBUG Filename
16.装入命令L(Load Command)
L命令用来将一个文件或磁盘指定扇区的内容装入内存,包括下列两种格式。
(1)L[<地址>]
将已用N命令的文件装入到指定内存单元,并将BX:CX设置为装入文件的字节数。对于可执行文件.EXE或.COM,通常不指定装入内存,由DEBUG分配,装入后自动设置CS:IP,一般IP为0(.EXE文件)或100H(.COM文件)。若指定地址,则可执行文件的装入地址必须是CS:100H。
(2)L<地址><驱动器号><起始逻辑扇区号><扇区数>
将磁盘的若干扇区(最多80H)装入到指定的内存地址。若只给出偏移地址,则使用CS当前值作为段地址。其中,0表示A盘,1表示B盘,2表示C盘,依此类推。例如,将C盘引导扇区(逻辑扇区号为0)的内容装入到内存地址为CS:0,然后查看,可用下列命令:
L 0 2 0 1
D CS:0
17.写盘命令W(Write Command)
W命令包括两种格式。
(1)W[<地址>]
将指定地址开始的BX:CX个字节写入已由N命令命名的文件中。若只给出偏移地址,则使用CS当前值作为段地址。若未指定地址,则缺省为CS:100H。
注意,在执行W命令前,必须正确设置BX和CX的值。另外,不能写入.EXE文件,因为.EXE文件必须以特定的格式才能写入,DEBUG不支持这种写入方式。
(2)W<地址><驱动器号><起始逻辑扇区号><扇区数>
将指定内存地址的数据写入磁盘的若干扇区(最多80H个)中。若只给出偏移地址,则使用CS当前值作为段地址。各参数的含义同L命令。
第二种格式的W命令直接将数据写入指定扇区,使用时一定要小心,否则会破坏磁盘上的文件系统乃至引导扇区。
18.端口输入命令I(Input Command)
I命令的格式为:
I<端口地址>
此命令从指定的I/O端口读入一个字节并显示。
19.端口输出命令O(Output Command)
O命令的格式为:
O<端口地址><字节>
用于输出一个字节到指定的I/O端口。