现在的位置: 首页 > 综合 > 正文

Debug使用手册2

2012年08月19日 ⁄ 综合 ⁄ 共 13562字 ⁄ 字号 评论关闭
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 DX=0041 SP=FFEE BP=0000 SI=0000 DI=0000
DS=127C ES=127C SS=127C CS=127C IP=0104 NV UP EI PL NZ NA PO NC
127C:0104 CD21 INT 21
-P
A
AX=0241 BX=0000 CX=0000 DX=0041 SP=FFEE BP=0000 SI=0000 DI=0000
DS=127C ES=127C SS=127C 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,41h就是大写A的ASCII码,身边有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 BA.6C FF.6C FF.6F B8.2C 00.57 AE.6F
127C:0208 CD.72 2F.6C 3C.64 00.24 C3.
-D 200
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..
127C: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.........
-A 100
127C:0100 MOV AH,09
127C:0102 MOV DX,0200
127C:0105 INT 21
127C:0107 INT 20
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"

抱歉!评论已关闭.