当前位置:首页 >> 电力/水利 >>

DEBUG的使用方法


DEBUG 的使用方法

原作者:jjg@cadence.com (John Gianni) 译者:fengmarcal@163.net(marcal) 我有两个理由发表这些文章: 1)给别人带来帮助: 用去我的一点时间就可以使到很多的朋友节省时间。译者注:我翻译的水平不高。但翻译的 目的是问了我们中国人也可以有多一点电脑高手,这样我们就可以早一点成为一个真正

的强 国。 2)同时我也将获得收益 一些关于 FAT/directory/data-sector-lookup 的知识我也需要帮助。 译者注: 我也一样希望 高手指正我翻译有误的地方。 以下就是正文了,你可以尝试一下(如果你发现问题,那么写信告诉我) 如何除错和汇编你的第一个 PC x86 汇编语言程序呢? 以下这些简单的解释可以让一个汇编语言新手使用 DEBUG: 0)在使用时,如何快速获得 debug 的使用帮助呢。 1)让我们开始工作吧,例如:显示 BIOS 的日期。 2)在你的电脑的 COMMANG.COM 文件里搜寻"IBM"这几个字符。 3) 一位十六进制数的运算。 4) 检查 x86 寄存器内容。 5)我们来编写我们的第一个用机械语言编写的程序-打印一个字符。 6) 我们现在用汇编语言指令来做和例 5 一样的事情。 7)现在,我们不但要编写一个汇编程序,而且我们还要把它存盘。 8) 现在,我们试一试查看一个已经编好的程序。 9)你可以用 DEBUG 的计算功能计算程序的长度。 10)另一种显示在屏幕上字符串的方法。 11)让我们试一试反复输出。 12)我们现在把两个程序连接起来。 13) 让我们逐步运行这个刚刚修补的程序。 14)如果一开始的命令不是跳转命令,那么可能就要用这种方法了。 以下所有的命令都是可以运行在 WIN9x 的 MS-DOS 方式下的。 进入 MS-DOS 的方式有: [开始][程序][MS-DOS 方式] [开始][运行][打开]COMMAND[确定] 或者你可以双击它:

C:\Windows\Command.com 0)在使用时,如何快速获得 debug 的使用帮助呢 以下 PROMPT>表示目录提示符:一般为:C:\WINDOWS\COMMAND\ PROMPT> DEBUG /?<按回车 press the enter key now> 怎样?出错了吧。显示如下 C:\WINDOWS>DEBUG/? Runs Debug, a program testing and editing tool. DEBUG [[drive:][path]filename [testfile-parameters]] [drive:][path]filename Specifies the file you want to test. testfile-parameters Specifies command-line information required by the file you want to test. After Debug starts, type ? to display a list of debugging commands. 因为错了所以它给你显示一些提示。留意到最后一句了吗?

现在我们再来试一试: PROMPT> DEBUG<按回车> (注意, DEBUG 程序的命令是在一条横线"-"后出现的。) -?<在出现的横线后面输入?再回车> (下面的内容是按字母顺序排列的) (注意:Note: Don't type the dash or comments -- just the ?) 显示如下,但是没有中文的哦,中文是我加上去的。

汇编 assemble A [address] 比较 compare C range address 倾倒 dump D [range] 进入 enter E address [list] 填充 fill F range list 进行 go G [=address] [addresses] 十六进制 hex H value1 value2 输入 input I port 装载 load L [address] [drive] [firstsector] [number] 移动 move M range address 命名 name N [pathname] [arglist] 输出 output O port byte 进行 proceed P [=address] [number] 离开 quit Q 纪录 register R [register] 搜寻 search S range list 描述 trace T [=address] [value] 反汇编 unassemble U [range]

写 write W [address] [drive] [firstsector] [number] 分配扩展内存 allocate expanded memory XA [#pages] 释放扩展内存 deallocate expanded memory XD [handle] map expanded memory pages XM [Lpage] [Ppage] [handle] display expanded memory status XS -q<按回车> (这是退出 DEBUG 回到 DOS 状态)This quits out of debug, returning to the DOS prompt) Tested examples below walk the user thru the following debug examples: 在下面的例子里读者必须明白以下几条 DEBUG 命令。 -D 显示一定范围内存的内容 Display the contents of an area of memory -Q 退出 DEBUG 程序 Quit the debug program -S 搜寻 Search for whatever -H 十六进制的运算 Hex arithmatic -R 显示或者改变一个或者多个寄存器的内容 Display or change the contents of one or more registers -E 输入数据进入内存,在一个详细的地址里 Enter data into memory, beginning at a specific location -G 运行现在在内存里的程序。Go run the executable program in memory -U 反汇编,把我们不认识的机械代码变为我们可以认识汇编语言符号 Unassemble machine code into symbolic code -T 描述一条指令的用法。Trace the contents of one instruction -P 进行或者执行一个相关的指令 Proceed, or execute a set of related instructions -A 编译,把汇编命令变为机械代码 Assemble symbolic instructions into machine code -N 命名一个程序 Name a program -W 把一个已经命名的程序写进磁盘 Write the named program onto disk -L 把程序装载进内存 Load the named program back into memory 返回目录 1)让我们开始工作吧,例如:显示 BIOS 的日期 (以下 PROMPT>表示目录提示符:一般为:C:\WINDOWS\COMMAND\) PROMPT> DEBUG<按回车> -D FFFF:0006 L 8<按回车> (显示 FFFFh, 偏移地址 6h, 长度 8 bytes) 在作者的电脑上这里显示为 "1/10/96." 译者的电脑显示" FFFF:0000 37 2F-30 36 2F 30 30 00 7/06/00."相信作者的电脑里也是用 这种格式显示的。这里显示出来的是使用者 BIOS 的日期,有兴趣的话可以重新开机看看,注 意开机时的显示。 -Q<按回车> (退出 DEBUG) 思考:当只按 DEBUG 的时候,编辑的是什么?为什么可以找到 BIOS 的日期?(译者这里也不 是很清楚所以请大家知道的也留言给斑竹,改正。译者认为可能是内存的真实物理地址。 )

返回目录 2)在你的电脑的 COMMANG.COM 文件里搜寻"IBM"这几个字符 下面的"C:\Win95\"是根据每不电脑不同的。像译者的电脑里就是"C:\WINDOWS" PROMPT> DEBUG C:\Win95\Command.com<按回车> -S 0 L FFFF "IBM"<按回车>(从 0 开始搜寻"IBM",搜寻 FFFFh 多个单元格) -Q<按回车> (退出 DEBUG) 以下是译者做的: C:\WINDOWS>DEBUG C:\WINDOWS\COMMAND.COM -S 0 L FFFF "IBM" -S 0 L FFFF "COMMAND" 12A7:008D 12A7:04F7 12A7:3870 12A7:38BE 12A7:38DD -S 0 L FFFF "PATH" 12A7:38AD 12A7:CCB7 12A7:CF55 -S 0 L FFFF "COMSPEC" 12A7:38D4 12A7:3A4D 12A7:CCC4 -Q C:\WINDOWS> (注意:搜寻是要区分大小写的) (你可以看到上面是没有找到"IBM"的, 可以试一试"PATH" , "COMSPEC" , "COMMAND") (注意: 这种方法用在查找加密资料和已被删除的资料等方面时是十分有用的) 返回目录 3) 一位十六进制数的运算: PROMPT> DEBUG<按回车> -H 9 1<按回车> (加减两个十六进制的数, 9h+1h=Ah & 9h-1h=8h) 结果是显示: 000A 0008 -Q<按回车> (退出 DEBUG)

C:\WINDOWS>debug -h 9 1 000A 0008 -q C:\WINDOWS> 返回目录 4) 检查 x86 寄存器内容 PROMPT> DEBUG<按回车> -R<按回车> (显示 x86 寄存器内容) -Q<按回车> (退出 DEBUG) C:\WINDOWS>debug -R AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=127C ES=127C SS=127C CS=127C IP=0100 NV UP EI PL NZ NA PO NC 127C:0100 043C ADD AL,3C -Q 下面是对寄存器的简单介绍: 数据存储器 在本类中,一般讲的 AH 就是 AX 的前八位,AL 就是 AX 的后八位,后面的以此类推。 AX Accumulator;作为累加器,所以它是算术运算的主要寄存器。另外所有的 I/O 指令都使 用这一寄存器与外部设备传送信息。 BX Base register;可以作为通用寄存器使用,此外在计算存储器地址时,它经常用作基地 址寄存器。 CX Counting register;可以作为通用寄存器使用,此外在循环(LOOP)和串处理指令中作隐 含的计数器。 DX Data register;可以作为通用寄存器使用,一般在作双字长运算时,把 DX 和 AX 组合在 一起存放一个双字长数,DX 用来存放高位字。此外,对某些 I/O 操作,DX 可用来存放 I/O 的端口地址。 指针及变址寄存器 BP Base pointers register ;机制指针寄存器 SI Source index register ;堆栈指针寄存器 DI Destiny index register ;目的变址寄存器 SP Battery pointer register ;堆栈指针寄存器 段寄存器 CS Code segment register ;代码段寄存器,存放正在运行的程序指令 DS Data segment register ;数据段寄存器,存放当前运行程序所用的数据

SS Battery segment register ;堆栈段寄存器,定义了堆栈所在区域 ES Extra segment register ;附加段寄存器,存放附加的数据,是一个辅助性的数据区, 控制寄存器 IP Next instruction pointer register;指令指针寄存器,它用来存放代码段中的偏移地 址,在程序运行的过程中,它始终指向下一条指令的首地址,它与 CS 寄存器联用确定下一条 指令的物理地址 F Flag register;标志寄存器 "NV UP EI PL NZ NA PO NC"就是了,也有人称之为 PSW Program Status Wold 程序状态寄存器 (这里有一点必须讲明白的现在在, 其实从奔腾开始这些寄存器(除了所有段寄存器,标志寄存 器 )都是 32 位的。并且加多了两个 16 位段寄存器 FS,GS。dos 下面看到这些寄存器是 16 位的。要看 32 位寄存器可以使用 soft-ice。对于 FS,GS 的作用我也不是很清楚,希望有高 手指点,谢谢。) 返回目录 5)我们来编写我们的第一个用机械语言编写的程序-打印一个字符 (这里用机械语言的主要原因是考虑到有一些用户不懂汇编命令,现在就要让他有一个认识 计算机程序实质是一些数字) PROMPT> DEBUG<按回车> -E 100<按回车> (在偏移地址为 100 的地方输入机械指令程序) B4<按空格>02<按空格> (在 AX 寄存器的前八位存入 02) B2<按空格>41<按空格> (在 DX 寄存器的后八位存入 41h,41h 就是大写 A 的 ASCII 码,身边 有 ASCII 表的朋友可以对着表改改数字试一试) CD<按空格>21<按空格> (当 AH=02 时这是 DOS 显示输出的中断号) CD<按空格>20<按回车> (退出 DOS) -G<按回车> (程序运行,并在屏幕上显示出"A") 程序运行完以后你将看到"Program terminated normally"(程序正常结束了). -U 100<按回车> (我们把它反汇编,就是把机械命令变为汇编语言指令) 107F:0100 B402 MOV AH,02 :0102 B2 MOV DL,41 :0104 CD21 INT 21 :0106 CD20 INT 20 (下面会有一堆无用的东西) (对了,你的段地址可能与我的段地址 CS=107F 不同哦) -R<按回车> (让我们来看看寄存器的值; IP==100h, AX==0000h, DX==0000h) 好极了,我们看到电脑又做好了准备下一次运行程序了。 -T<按回车> (执行第一步操作... IP=>102h, AX=>0200h,指令指针寄存器指向下一条命令, AX 的值被改变。 -T<按回车> (执行第二步操作... IP=>104h, , DX=>0041h,指令指针寄存器指向下一条命令, DX 的值被改变。 -P<按回车> (继续执行 INT 21,IP=>106h, AX=>02h,)

-P<按回车> (继续执行 INT 20) -Q<按回车> (退出 DEBUG) (注意: 你必须小心使用"T".因为如果你在程序完结以后继续执行这条命令, 因为我们无法预 知下面的指令是什么,所以我们也无法预知它可能带来的后果) C:\WINDOWS>DEBUG -E 100 127C:0100 B4.B4 02.02 B2.B2 41.41 CD.CD 21.21 CD.CD 20.20 -G A Program terminated normally -U 100 127C:0100 B402 MOV AH,02 127C:0102 B241 MOV DL,41 127C:0104 CD21 INT 21 127C:0106 CD20 INT 20 127C:0108 C706F1E30900 MOV WORD PTR [E3F1],0009 127C:010E EB59 JMP 0169 127C:0110 57 PUSH DI 127C:0111 BFF1E3 MOV DI,E3F1 127C:0114 8BDF MOV BX,DI 127C:0116 06 PUSH ES 127C:0117 0E PUSH CS 127C:0118 07 POP ES 127C:0119 32D2 XOR DL,DL 127C:011B EB34 JMP 0151 127C:011D 006B12 ADD [BP+DI+12],CH -R AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=127C ES=127C SS=127C CS=127C IP=0100 NV UP EI PL NZ NA PO NC 127C:0100 B402 MOV AH,02 -T AX=0200 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=127C ES=127C SS=127C CS=127C IP=0102 NV UP EI PL NZ NA PO NC 127C:0102 B241 MOV DL,41 -T AX=0200 BX=0000 CX=0000 DS=127C ES=127C SS=127C 127C:0104 CD21 INT 21 -P A AX=0241 BX=0000 CX=0000 DS=127C ES=127C SS=127C DX=0041 SP=FFEE BP=0000 SI=0000 DI=0000 CS=127C IP=0104 NV UP EI PL NZ NA PO NC

DX=0041 SP=FFEE BP=0000 SI=0000 DI=0000 CS=127C IP=0106 NV UP EI PL NZ NA PO NC

127C:0106 CD20 INT 20 -P Program terminated normally -Q C:\WINDOWS> 返回目录 6) 我们现在用汇编语言指令来做和例 5 一样的事情 PROMPT> DEBUG<按回车> -A 100<按回车> (在偏移地址为 100 的地方输入汇编语言程序) MOV AH,02<按回车> (选用 DOS 的 02 号功能调用,显示输出) MOV DL,<按回车> (在 DX 寄存器的后八位存入 41h, 就是大写 A 的 ASCII 码, 41h 身边有 ASCII 表的朋友可以对着表改改数字试一试) INT 21<按回车> (当 AH=02 时这是 DOS 显示输出的中断号,显示"A") INT 20<按回车> (退出 DOS) <按回车> (结束汇编语言编程状态,回到 DEBUG 命令状态) -G =100<按回车> (运行程序,其实可以不要"=100"因为一般默认启始位置是 100) -Q<按回车> (退出 DEBUG)

C:\WINDOWS>DEBUG -A 100 127C:0100 MOV AH,02 127C:0102 MOV DL,41 127C:0104 INT 21 127C:0106 INT 20 127C:0108 -G A Program terminated normally -Q 返回目录 7) 现在,我们不但要编写一个汇编程序,而且我们还要把它存盘 (下面这个程序就要比原来的程序复杂一点了-显示输出:"ABC") PROMPT> DEBUG<按回车>(运行 DEBUG 程序;系统默认启始 IP 寄存器值为 100h) -A 100<按回车> (用汇编语言编写一个程序,启始地址是 100h) MOV AH,02<按回车> (选择 DOS 的 02 号功能调用, 显示输出)

MOV DL,<按回车> (在 DX 寄存器的后八位存入 41h,41h 就是大写 A 的 ASCII 码) INT 21<按回车> (当 AH=02 时这是 DOS 显示输出的中断号,显示"A") MOV DL,42<按回车> (在 DX 寄存器的后八位存入 41h,41h 就是大写 B 的 ASCII 码) INT 21<按回车> (当 AH=02 时这是 DOS 显示输出的中断号,显示"B") MOV DL,43<按回车> (在 DX 寄存器的后八位存入 41h,41h 就是大写 C 的 ASCII 码) INT 21<按回车> (当 AH=02 时这是 DOS 显示输出的中断号,显示"C") INT 20<按回车> (程序结束,退出 DEBUG) <按回车> (结束汇编命令输入,回到 DEBUG 命令输入) -R BX<按回车> (查看寄存器 BX 的值) :0000<按回车> (设置 BX 为 0000h,这是程序的结尾地址是 BX:CX) (注意,只要 BX = 0000, 文件的大小就小于 < 64 Kb.) -R CX<按回车> (设置 CX 为 Fh,这是程序的长度:16 位) :0010<按回车> (现在我们可以把这个 16 字节的程序写入硬盘了) -N printabc.com<按回车> (将要存盘的程序命名) -W<按回车> (把这十六字节写到文件里面) -Q<按回车> (退出 DEBUG) PROMPT> DIR printabc.com<按回车> 这里将会报告这个文件的大小是 16 字节 (10h 字节). PROMPT> printabc.com<按回车> 会马上在屏幕上打印出"ABC" C:\WINDOWS>DEBUG -A 100 127C:0100 MOV AH,02 127C:0102 MOV DL,41 127C:0104 INT 21 127C:0106 MOV DL,42 127C:0108 INT 21 127C:010A MOV DL,43 127C:010C INT 21 127C:010E INT 20 127C:0110 -R AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=127C ES=127C SS=127C CS=127C IP=0100 NV UP EI PL NZ NA PO NC 127C:0100 B402 MOV AH,02 -R BX BX 0000 : -R CX CX 0000 :0010 -N PRINTABC.COM -W

Writing 00010 bytes -Q C:\WINDOWS>DIR PRINTABC.COM Volume in drive C has no label Volume Serial Number is 28FB-70BA Directory of C:\WINDOWS PRINTABC COM 16 03-21-01 11:02 PRINTABC.COM 1 file(s) 16 bytes 0 dir(s) 557,711,360 bytes free C:\WINDOWS>PRINTABC ABC C:\WINDOWS> 这里可以有人告诉我,为什么要存入是 BX:CX 代表程序长度吗?(写信给译者,谢谢) 返回目录 8) 现在,我们试一试查看一个已经编好的程序: PROMPT> DEBUG<按回车>(运行 DEBUG 程序在 CS:IP = CS:0100h) -N printabc.com<按回车> (告诉电脑你想装载的程序名) -L<按回车> (装载那个名字的程序进入内存) -U 100 L 10<按回车> (从偏移地址 100 开始反汇编 16 位字节) -R<按回车> (现在看看寄存器里面的内容) 注意:DEBUG 本身是没有自动纪录文件大小的。 -G (运行被命名的程序,打印"ABC") 你将看到"ABC",然后是"Program terminated normally") C:\WINDOWS>DEBUG -N PRINTABC.COM -L -U 100 L 10 12A4:0100 B402 MOV AH,02 12A4:0102 B241 MOV DL,41 12A4:0104 CD21 INT 21 12A4:0106 B242 MOV DL,42 12A4:0108 CD21 INT 21 12A4:010A B243 MOV DL,43 12A4:010C CD21 INT 21 12A4:010E CD20 INT 20 -R AX=0000 BX=0000 CX=0010 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000 DS=12A4 ES=12A4 SS=12A4 CS=12A4 IP=0100 NV UP EI PL NZ NA PO NC 12A4:0100 B402 MOV AH,02

-G ABC Program terminated normally 返回目录 9)你可以用 DEBUG 的计算功能计算程序的长度。 一开始的时候你的程序初始地址是在 0100h: 107F:0100 MOV AH,02 <--这就是 100h 你的程序的最后一行在 010Eh: 107F:010E INT 20 <--最后一行 然后,最后一条命令的下一行的地址是 0110h: 107F:0110 <--这就是 110h 所以,从 0110h 里减去 100h 我们得到得长度是 10h 字节. PROMPT> DEBUG<按回车> -H 110 100<按回车> (这条命令将运算 110h+100h 和 110h-100h) 0210 0010<按回车> (汇报 110h-100h=0010h; 16-byte 程序长度 16 位) -Q<按回车> (退出 DEBUG)

C:\WINDOWS>debug -H 110 100 0210 0010 -Q 返回目录 10)另一种显示在屏幕上字符串的方法 注意:在你输入数据的时候,按"-"键将会可以让你回退一格。 PROMPT> DEBUG<按回车> -E 200<按回车> (从偏移地址 200 开始。输入"Hello,World") 48<按空格>65<按空格> (输入 48h (H)和 65h (e)) 6C<按空格>6C<按空格> (输入 6Ch (l)和 6Ch (l)) 6F<按空格>2C<按空格> (输入 6Fh (o)和 2Ch (,)) 57<按空格>6F<按空格> (输入 57h (W)和 6Fh (o)) 72<按空格>6C<按空格> (输入 72h (r)和 6Ch (l)) 64<按空格>24<按空格> (输入 64h (d)和 24h ($)) <按回车> ("Hello,World" 已经输入完毕) -D 200<按回车> (显示你刚刚输入的内容: 48 65 6C 6C 6F 2C 57 6F-72 6C 64 24 ... HELLO,WORLD$...)

-A 100<按回车> (用汇编语言写一个新程序在 IP-100h 处开始) MOV AH,09<按回车> (选择 DOS 的 09 号功能调用,显示字符串) MOV DX,0200<按回车> (把输出地址(200h),放进寄存器) INT 21<按回车> (执行 DOS 功能调用,显示"Hello,World") INT 20<按回车> (退出程序回到 DOS 状态) <按回车> (结束汇编语言输入,回到 DEBUG 输入状态) -G<按回车> (从 CS:IP 开始运行程序, 就是从 107F:0100h 开始执行程序) 现在,我们可以把这个程序保存进一硬盘 -D 100<按回车> (纪录:程序的起始点在 100h) -D 200<按回车> (纪录:程序数据单元的结束点是在 020Bh) -H 20B 100<按回车> (运算 20Bh-100h=10Bh;程序长度 267 字节) -R BX<按回车> (检查 BX 寄存器的值) :0000<按回车> (设置 BX 为 0000h,程序的长度是 BX:CX,实际上你可以把和 CX 写到一起, 即实际长度为:0000010Bh,这样些的目的是使你可以计算更大的程序的长度) -R CX<按回车> (设置 CX 为 010Bh, 这就是这个程序的长度了) :010B<按回车> (现在你可以把这个 108 字节的程序写入硬盘了) -N printhw.com<按回车> (将要写入硬盘的程序命名) -W<按回车> (把这 10Bh 即 267 个字节写入文件) -Q<按回车> (退出 DEBUG) PROMPT> DIR printhw.com<按回车> 将会汇报程序的长度是 267 字节(10Bh 字节). PROMPT> printhw.com<按回车> 运行这个程序,这将会在屏幕上显示出"Hello,World" : C:\WINDOWS>DEBUG -E 200 127C:0200 2C.48 D5.65 127C:0208 CD.72 2F.6C -D 200 127C:0200 48 65 6C 6C 127C:0210 0A C0 74 09 127C:0220 FC 56 57 F3 127C:0230 C3 23 74 19 127C:0240 D4 74 0A 41 127C:0250 A1 F3 D8 8B 127C:0260 00 8B 36 F5 127C:0270 2B DE 59 03 -A 100 127C:0100 MOV AH,09 127C:0102 MOV DX,0200 127C:0105 INT 21 127C:0107 INT 20

BA.6C FF.6C FF.6F B8.2C 00.57 AE.6F 3C.64 00.24 C3. 6F 56 A4 3C 3C 36 D8 CB 2C 57 5F 0D 22 F5 8B 8B 57 E8 5E 74 75 D8 0E D6 6F-72 84-21 C3-50 15-F6 E6-80 C6-06 F3-D8 C6-06 6C 5F 56 C7 F7 37 8B D7 64 5E 33 20 20 DA D6 DC 24 73 C9 75 EB 00 E3 00 C3 0A 33 06 E1 C6 42 E3 A0 B9 DB 3A 5E 06 51 31 ED 04 AC 06 58 33 56 49 E3 01 E8 1E C3 DA 5B AC Hello,World$ ..t.VW..!_^s .VW.._^.PV3. .#t.<.t... u .t.A<"u... . ....6....7.. ..6......... +.Y.........

127C:0109 -G Hello,World Program terminated normally -D200 127C:0200 48 65 6C 6C 6F 2C 57 6F-72 6C 64 24 C3 A0 ED E3 Hello,World$ 127C:0210 0A C0 74 09 56 57 E8 84-21 5F 5E 73 0A B9 04 01 ..t.VW..!_^s 127C:0220 FC 56 57 F3 A4 5F 5E C3-50 56 33 C9 33 DB AC E8 .VW.._^.PV3. 127C:0230 C3 23 74 19 3C 0D 74 15-F6 C7 20 75 06 3A 06 1E .#t.<.t... u 127C:0240 D4 74 0A 41 3C 22 75 E6-80 F7 20 EB E1 5E 58 C3 .t.A<"u... . 127C:0250 A1 F3 D8 8B 36 F5 D8 C6-06 37 DA 00 C6 06 33 DA ....6....7.. 27C:0260 00 8B 36 F5 D8 8B 0E F3-D8 8B D6 E3 42 51 56 5B ..6......... 127C:0270 2B DE 59 03 CB 8B D6 C6-06 D7 DC 00 E3 31 49 AC +.Y......... -H 20B 100 030B 010B -R BX BX 0000 : -R CX CX 0000 :010B -N PRINTHW.COM -W Writing 0010B bytes -Q C:\WINDOWS>DIR PRINTHW.COM Volume in drive C has no label Volume Serial Number is 28FB-70BA Directory of C:\WINDOWS PRINTHW COM 267 03-22-01 11:53 PRINTHW.COM 1 file(s) 267 bytes 0 dir(s) 555,089,920 bytes free 返回目录 11)让我们试一试反复输出: PROMPT> DEBUG<按回车> -A 100<按回车> (用汇编语言写一个新的程序,起始地址是 100h) JMP 125<按回车> (从 102h 接跳到 125h) <按回车> (结束输入汇编命令。译者注:这里是为了例 12 做准备) -E 102 'Hello World' 0d 0a '$'<按回车> (把字符串输入内存) -A 125<按回车> (从 125h 开始继续编写我们的汇编语言程序) MOV DX,0102<按回车> (把字符串的首地址(102h)放入 DX 寄存器)

MOV CX,0005<按回车> (指定这条指令将被显示 5 次) MOV AH,09<按回车> (选择 DOS 的 09 号功能调用, 显示字符串) INT 21<按回车> (执行 DOS 的功能调用, 显示"Hello, World") DEC CX<按回车> (每次运行到这里 CX 都减去 1) JCXZ 0134<按回车> (如果计数器 CX=0,那么跳到地址 0134h) JMP 012D<按回车> (其他情况下,即 CX≠O 时跳到 012Dh) INT 20<按回车> (程序退出 DOS 状态) <按回车> (结束汇编语言程序输入,回到 DEBUG) -U 100<按回车> (从地址 100h 开始反汇编) -U<按回车> (继续执行反汇编指令,直至你看到 INT 20) -H 0136 100<按回车> (运算程序长度为 36h) -U 100 L 36<按回车> ( 从 100h 反汇编到 136h ,来确认你的计算) -R BX<按回车> (查看寄存器 BX 的值) :0000<按回车> (设置 BX 为 0000h) -R CX<按回车> (把 CX 设置为 36h, 这就是程序长度 36 字节) :0036<按回车> (现在你可以把这 36 字节写入文件了) -N printhw5.com<按回车>(命名我,我们要写入的文件名) -W<按回车> (把这 36 字节的内容写进新文件) -G<按回车> (运行程序,在屏幕上显示"Hello-World ") -Q<按回车> (退出 DEBUG) PROMPT> DIR printhw5.com<按回车> 将会汇报文件大小为 54 字节,换算为十六进制就是 36h 字节 PROMPT> printhw5.com<按回车> 将在屏幕上显示五次"Hello World" 返回目录 12)我们现在把两个程序连接起来。 我们现在把 printhw.com 做为修补程序 写进 printhw5.com, 新版本的 printhw5 将先执行原 来的 printhw.com 再执行原来的 printhw5.com PROMPT> COPY printhw5.com printhw5.bak<按回车> 首先,备份 printhw5.com,以后可以用于比较 PROMPT> DIR printhw5.com<按回车> 现在,查看到得仍然是以前的 54 字节(36h 字节) PROMPT> DEBUG printhw5.com<按回车> -R<按回车> (现在查看仍然是 BX:CX=0000 0036h bytes) -U 100<按回车> (查看到最后的是 EB 23 (JMP 0125)) -H 100 36<按回车> (最后的指令是在 100h+36h=136h) -H 136 1<按回车> (下一个可用的存储器位置是 136h+1h=137h) 现在你拥有足够的资料,去修补那个程序 -E 110<按回车> (把"Hello,World"输入内存) 48<按空格>65<按空格> (输入 48h (H)和 65h (e))

6C<按空格>6C<按空格> (输入 6Ch (l)和 6Ch (l)) 6F<按空格>2C<按空格> (输入 6Fh (o)和 2Ch (,)) 57<按空格>6F<按空格> (输入 57h (W)和 6Fh (o)) 72<按空格>6C<按空格> (输入 72h (r)和 6Ch (l)) 64<按空格>24<按空格> (输入 64h (d)和 24h ($)) <按回车> (停止输入"Hello,World") -D 110<按回车> (显示更才输入内存的数据: 48 65 6C 6C 6F 2C 57 6F-72 6C 64 24 ...HELLO,WORLD$...) -A 100<按回车> (在 IP 地址的 (100h) 开始夺取原来的程序的控制权, 原来这里是"JMP 125") JMP 137<按回车> (代替原来运行的程序首先运行我们现在的修补程序) <按回车> (结束汇编命令输入,回到 DEBUG 命令输入) -A 137<按回车> (在下面的可用通奸编译这个修补程序) MOV AH,09<按回车> (选择 DOS 的 09 号功能调用,显示输出) MOV DX,110<按回车> (把我们要输出的字段的首地址(110h)给 DX 寄存器) INT 21<按回车> (执行 DOS 的功能调用,显示"Hello,World") JMP 0125<按回车> (这里用跳转到原程序来代替退出到 DOS 命令(INT 20)) <按回车> (结束汇编命令输入,回到 DEBUG 命令输入) -U 125<按回车> (确认一下源程序没有被我们误改了,如果无改了就马上退出 DEBUG 重新来 过) -U 100 L 1<按回车> (确认已经使程序跳转到我们的修补程序地址 137h) -D 110 L C<按回车> (确认数据区已经有了我们想要的数据) -U 137<按回车> (确认我们的新程序已经输入了) 现在我们可以把这个小程序存入硬盘了: (注意:在现在整个程序的最后一条命令"JMP 0125" 的后面一条的地址是 0140h) -H 0140h 100<按回车> (计算 140h-100h=40h; 答案是我们现在有一个长度为 64 字节的小程 序) -RBX<按回车> (检查 BX 寄存器的值是否为"0") :<按回车> (如果 BX 是 0000h 那么就不需要改动啦) -RCX<按回车> (要把 CX 改为 40h。这是我们的程序的长度) :40<按回车> (现在你可以把这 0000:0040h 个字节的小程序放入硬盘啦) -W<按回车> (覆盖我们的原程序) -G<按回车> (尝试运行我们的新程序) -Q<按回车> (退出 DEBUG 回到 DOS) PROMPT> DIR printhw5.com<按回车> 现在你再看就发现文章大小不再是 54 字节, 变成了 64 字节. PROMPT> printhw5.com<按回车> 现在是首先在屏幕上打印 "Hello,World"一次,然后再打印"Hello,World" 5 次(译者注: 这里其实可以在编程的时候换一换内容试一试. 返回目录

13) 让我们逐步运行这个刚刚修补的程序: PROMPT> DEBUG printhw5.com<按回车> -R<按回车> (第 1 步:地址 0100h 内容是 EB35 "JMP 0137") -T<按回车> (第 2 步:地址 0137h 内容是 B409 "MOV AH,09") -T<按回车> (第 3 步:地址 0139h 内容是 BA1001 "MOV DX,0110") -T<按回车> (第 4 步:地址 0139h 内容是 CD21 "INT 21") -P<按回车> (运行第 5:"Hello,World"地址 013Eh 内容是 EBE5 "JMP 0125") -T<按回车> (到这里控制权已经回到了原程序) 如果你想的话,你可以一步一步的执行完全部程序;方法就是一直按"T",直至到达下一个功 能调用运行完成后。到那时按一个"P"就可以继续按"T". 返回目录 14)如果一开始的命令不是跳转命令,那么可能就要用这种方法了: 例如:如果我们想叫程序 printhw 先打印"ABC",就要获取控制权了。然后打印"ABC"的程序 把控制权给回原来的 printhw. 在这个事例里 ,printhw 在 100h 的地址有两字节的程序; 不能象上面那样简单的替代(一个 JMP 代替另一个 JMP)就完事。 解决办法就是使用 NOP 命令。

PROMPT> DIR printhw.com<按回车> 将汇报程序的长度为 267 字节(10Bh 字节). PROMPT> DEBUG printhw.com<按回车> -R<按回车> (IP=100h 并且 printhw's 的文件大小=BX:CX=0000:010Bh) -U 100<按回车> (第一条指令 B4 09 (MOV AH,09)是两个字节的) (第二条命令是三个字节的 BA 00 02 (MOV DX,0200)) -H 100 10B<按回车> (最后一条 printhw 的指令是在 100h+10Bh=20Bh) (DOS 的 INT 21 功能调用是在 105h 开始的) 现在你有足够的资料输入你的程序了! -A 100<按回车> (要在 printhw 的 IP 开始位置就夺取程序的控制权) JMP 20B<按回车> (跳到 20Bh 增加一个程序) NOP<按回车> (用空指令填充直至你去到下一条完整的指令) NOP<按回车> (你可以用它来覆盖你不想只执行的原程序命令 ,而不改变原来的地址。但是 在这里我们只需要两个 NOP) 译者注:为了使大家更加明白所以我将各条命令对应的机械命令的长度写在下面 B409 MOV AH,09 BA0002 MOV DX,0200 E90301 JMP 020B 90 NOP

这样我们就很清楚的看到 JMP 020B 的长度比 MOV AH,09 多了 1 个字节,但是 MOV DX,0200 有是 3 个字节,而 NOP 是空指令,是不执行任何操作的,它只是占 1 个字节。所以我们现在 把前两条指令用一个 JMP 020B 和两个 NOP 代替。后面再加上去。 <按回车> (结束汇编命令回到 DEBUG 命令输入) -U 100<按回车> (看一看前面我们做了些什么) (注意 DOS INT 21 中断任然是在 IP=105h 的地方开始) -A 20B<按回车> (现在把我们的原程序写在后面) MOV AH,02<按回车> (选择 DOS 的 2 号功能调用, 字符显示输出) MOV DL,41<按回车> (在 DL 寄存器存入"A"的 ASCII 码 41h) INT 21<按回车> (执行 DOS 的功能调用,显示字符"A") MOV DL,42<按回车> (在 DL 寄存器存入"B"的 ASCII 码 42h) INT 21<按回车> (执行 DOS 的功能调用,显示字符"B") MOV DL,43<按回车> (在 DL 寄存器存入"C"的 ASCII 码 43h) INT 21<按回车> (执行 DOS 的功能调用,显示字符"C") MOV AH,09<按回车> (现在重新输入原来在 100h 的程序指令) MOV DX,0200<按回车> (现在要打扫寄存器了,还原原来的 200h 的值) JMP 105<按回车> (跳到 INT 21 指令的位置 105h) <按回车> (请注意一下你这里最后的地址是 0221h) -H 221 100<按回车> (计算 221h-100h=121h 就是 289 字节的程序) -R CX<按回车> (把 CX 的值设为 121h, 这就设定了程序的新长度) :0121<按回车> (现在用 121h (也就是 289 字节)覆盖原值) -W<按回车> (把这 289 个字节写回原程序) -Q<按回车> (退出 DEBUG) PROMPT> DIR printhw.com<按回车> 现在在看就会是新程序的长度 289 字节而不是 267 字节 现在在屏幕上先出现"ABC"再出现"Hello,World"


相关文章:
DEBUG的使用方法
DEBUG的使用方法_IT/计算机_专业资料。DEBUG 程序的使用 程序的使的提示符下, 启动调试程序: 一、在 DOS 的提示符下,可如下键入 Debug 启动调试程序: DEBUG [...
Debug使用方法
Debug使用方法_电脑基础知识_IT/计算机_专业资料。DEBUG 使用方法启动 DEBUG 程序,DEBUG 程序用于调试可执行文件。 格式: DEBUG[[drive:][path]filename[testfile-...
DEBUG使用方法简介
DEBUG使用方法简介_IT/计算机_专业资料。微机系统(DUBGE、8086等)2.3 DEBUG 使用方法简介: DEBUG 是 DOS 命令,必须在 DOS 环境下运行。由于目前都使用 WINDOWS ...
汇编步骤和Debug使用方法
汇编步骤和Debug使用方法_IT/计算机_专业资料。实验预备知识一、 汇编程序的建立 1. 使用工具 汇编程序的建立与调试 (1)EDIT,记事本等文本编辑软件,编辑源程序,...
debug用法大全
++ 说明 使用 Debug 命令但不指定要测试的文件 如果使用没有位置和文件名的 Debug 命令,然后键入所有的 Debug 命令以响应 Debug 提示符,连字符 (-)。 Debug ...
VIVADO中debug用法
(1) 第一种方法是在 Netlist 窗口中选择信号,右键点击 Mark Debug 8 VIVADO 中 debug 用法 (2) 第二种方法是在 Tools 中选择 Setup Debug 推荐使用方法 ...
在DOS下的DEBUG命令的详细用法
在DOS下的DEBUG命令的详细用法_电脑基础知识_IT/计算机_专业资料。选填,简要介绍文档的主要内容,方便文档被更多人浏览和下载。1263969482 一级 | 我的知道 | 消息...
DEBUG使用方法
DEBUG使用方法_工学_高等教育_教育专区。快速学会debug的使用 DEBUG 使用方法格式: DEBUG[[drive:][path]filename[testfile-parameters]] 参数:[drive:][path]...
DEBUG 使用方法
DEBUG 使用方法DEBUG 是专门为汇编语言设计的一种调试工具软件, 可用来检查、 修改寄存器和内存单元 的内容,装入运行程序,汇编及反汇编机器语言程序,可用...
更多相关标签:
debug | eclipse中debug的使用 | debug的用法 | debug的使用 | httpdebug的使用方法 | debug使用方法 | lua debug 使用方法 | debugview使用方法 |