DEBUG是為匯編語言設計的一種高度工具,它通過單步、設置斷點等方式為匯編語言程序員提供了非常有效的調(diào)試手段。
一、DEBUG程序的調(diào)用
在DOS的提示符下,可鍵入命令:
C:\DEBUG [D:][PATH][FILENAME[.EXT]][PARM1][PARM2]
其中,文件名是被調(diào)試文件的名字。如用戶鍵入文件,則DEBUG將指定的文件裝入存儲器中,用戶可對其進行調(diào)試。如果未鍵入文件名,則用戶可以用當前存儲器的內(nèi)容工作,或者用DEBUG命令N和L把需要的文件裝入存儲器后再進行調(diào)試。命令中的D指定驅(qū)動器PATH為路徑,PARM1和PARM2則為運行被調(diào)試文件時所需要的命令參數(shù)。
在DEBUG程序調(diào)入后,將出現(xiàn)提示符,此時就可用DEBUG命令來調(diào)試程序。
二、DEBUG的主要命令
1、顯示存儲單元的命令D(DUMP),格式為:
_D[address]或_D[range]
例如,按指定范圍顯示存儲單元內(nèi)容的方法為:
-d100 120
18E4:0100 c7 06 04 02 38 01 c7 06-06 02 00 02 c7 06 08 02 G...8.G.....G...
18E$:0110 02 02 bb 04 02 e8 02 00-CD 20 50 51 56 57 8B 37 ..;..h..M PQVW.
7
18E4:0120 8B
其中0100至0120是DEBUG顯示的單元內(nèi)容,左邊用十六進制表示每個字節(jié),右邊用ASCII字符表示每個字節(jié),·表示不可顯示的字符。這里沒有指定段地址,D命令自動顯示DS段的內(nèi)容。如果只指定首地址,則顯示從首地址開始的80個字節(jié)的內(nèi)容。如果完全沒有指定地址,則顯示上一個D命令顯示的最后一個單元后的內(nèi)容。
2、修改存儲單元內(nèi)容的命令有兩種。
·輸入命令E(ENTER),有兩種格式如下:第一種格式可以用給定的內(nèi)容表來替代指定范圍的存儲單元內(nèi)容。命令格式為:
-E address [list]
例如,-E DS:100 F3'XYZ'8D
其中F3,'X','Y','Z'和各占一個字節(jié),該命令可以用這五個字節(jié)來替代存儲單元DS:0100到0104的原先的內(nèi)容。
第二種格式則是采用逐個單元相繼修改的方法。命令格式為:
-E address
例如,-E DS:100
則可能顯示為:
18E4:0100 89.-
如果需要把該單元的內(nèi)容修改為78,則用戶可以直接鍵入78,再按"空格"鍵可接著顯示下一個單元的內(nèi)容,如下:
18E4:0100 89.78 1B.-
這樣,用戶可以不斷修改相繼單元的內(nèi)容,直到用ENTER鍵結束該命令為止。
·填寫命令F(FILL),其格式為:
-F range list
例如:-F 4BA:0100 5 F3'XYZ'8D
使04BA:0100~0104單元包含指定的五個字節(jié)的內(nèi)容。如果list中的字節(jié)數(shù)超過指定的范圍,則忽略超過的項;如果list的字節(jié)數(shù)小于指定的范圍,則重復使用list填入,直到填滿指定的所有單元為止。
3)檢查和修改寄存器內(nèi)容的命令R(register),它有三種格式如下:
·顯示CPU內(nèi)所有寄存器內(nèi)容和標志位狀態(tài),其格式為:
-R
例如,-r
AX=0000 BX=0000 CX=010A DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000
DS=18E4 ES=18E4 SS=18E4 CS=18E4 IP=0100 NV UP DI PL NZ NA PO NC
18E4:0100 C70604023801 MOV WORD PTR [0204],0138 DS:0204=0000
·顯示和修改某個寄存器內(nèi)容,其格式為:
-R register name
例如,鍵入
-R AX
系統(tǒng)將響應如下:
AX F1F4
:
即AX寄存器的當前內(nèi)容為F1F4,如不修改則按ENTER鍵,否則,可鍵入欲修改的內(nèi)容,如:
-R bx
BX 0369
:059F
則把BX寄存器的內(nèi)容修改為059F。
·顯示和修改標志位狀態(tài),命令格式為:
-RF系統(tǒng)將響應,如:
OV DN EI NG ZR AC PE CY-
此時,如不修改其內(nèi)容可按ENTER鍵,否則,可鍵入欲修改的內(nèi)容,如:
OV DN EI NG ZR AC PE CY-PONZDINV
即可,可見鍵入的順序可以是任意的。
4)運行命令G,其格式為:
-G[=address1][address2[address3…]]
其中,地址1指定了運行的起始地址,如不指定則從當前的CS:IP開始運行。后面的地址均為斷點地址,當指令執(zhí)行到斷點時,就停止執(zhí)行并顯示當前所有寄存器及標志位的內(nèi)容,和下一條將要執(zhí)行的指令。
5)跟蹤命令T(Trace),有兩種格式:
·逐條指令跟蹤
-T [=address]
從指定地址起執(zhí)行一條指令后停下來,顯示所有寄存器內(nèi)容及標志位的值。如未指定地址則從當前的CS:IP開始執(zhí)行。
·多條指令跟蹤
-T [=address][value]
從指定地址起執(zhí)行n條指令后停下來,n由value指定。
6)匯編命令A(Assemble),其格式為:
-A[address]
該命令允許鍵入?yún)R編語言語句,并能把它們匯編成機器代碼,相繼地存放在從指定地址開始的存儲區(qū)中。必須注意:DEBUG把鍵入的數(shù)字均看成十六進制數(shù),所以如要鍵入十進制數(shù),則其后應加以說明,如100D。
7)反匯編命令U(Unassemble)有兩種格式。
·從指定地址開始,反匯編32個字節(jié),其格式為:
-U[address]
例如:
-u100
18E4:0100 C70604023801 MOV WORD PTR[0204],0138
18E4:0106 C70606020002 MOV WORD PTR[0206],0200
18E4:010C C70606020202 MOV WORD PTR[0208],0202
18E4:0112 BBO4O2 MOV BX,0204
18E4:0115 E80200 CALL 011A
18E4:0118 CD20 INT 20
18E4:011A 50 PUSH AX
18E4:011B 51 PUSH CX
18E4:011C 56 PUSH SI
18E4:011D 57 PUSH DI
18E4:011E 8B37 MOV SI,[BX]
如果地址被省略,則從上一個U命令的最后一條指令的下一個單元開始顯示32個字節(jié)。
·對指定范圍內(nèi)的存儲單元進行反匯編,格式為:
-U[range]
例如:
-u100 10c
18E4:0100 C70604023801 MOV WORD PTR[0204],0138
18E4:0106 C70606020002 MOV WORD PTR[0206],0200
18E4:010C C70606020202 MOV WORD PTR[0208],0202
或
-u100 112
18E4:0100 C70604023801 MOV WORD PTR[0204],0138
18E4:0106 C70606020002 MOV WORD PTR[0206],0200
18E4:010C C70606020202 MOV WORD PTR[0208],0202
可見這兩種格式是等效的。
8)命名命令N(Name),其格式為:
-N filespecs [filespecs]
命令把兩個文件標識符格式化在CS:5CH和CS:6CH的兩個文件控制塊中,以便在其后用L或W命令把文件裝入存盤。filespecs的格式可以是:
[d:][path] filename[.ext]
例如,
-N myprog
-L
-
可把文件myprog裝入存儲器。
來自 紫色星云
狀態(tài) 離線 9)裝入命令(Load),有兩種功能。
·把磁盤上指定扇區(qū)范圍的內(nèi)容裝入到存儲器從指定地址開始的區(qū)域中。其格式為:
-L[address[drive sector sector]
·裝入指定文件,其格式為:
-L[address]
此命令裝入已在CS:5CH中格式化了文件控制塊所指定的文件。如未指定地址,則裝入CS:0100開始的存儲區(qū)中。
10)寫命令W(Write),有兩種功能。
·把數(shù)據(jù)寫入磁盤的指定扇區(qū)。其格式為:
-W address drive sector sector
·把數(shù)據(jù)寫入指定的文件中。其格式為:
-W[address]
此命令把指定的存儲區(qū)中的數(shù)據(jù)寫入由CS:5CH處的文件控制塊所指定的文件中。如未指定地址則數(shù)據(jù)從CS:0100開始。要寫入文件的字節(jié)數(shù)應先放入BX和CX中。
11)退出DEBUG命令Q(Quit),其格式為:
-Q
它退出DEBUG,返回DOS。本命令并無存盤功能,如需存盤應先使用W命令。
問題:初學者問一個低級問題,執(zhí)行debug-a后,如果有一行輸入錯誤,如何更改這一行?
回答:
加入進行如下輸入:
D:\PWIN95\Desktop>debug
-a
2129:0100movax,200
2129:0103movbx,200
2129:0106movcx,200
2129:0109
此時,發(fā)現(xiàn)movbx,200一句錯誤,應為movbx,20,可以敲回車返回"-"狀態(tài),然后輸入:
-a103
2129:0103movbx,20
如果多或者少若干行,不必重新輸入,可以用M命令移動后面的程序來去掉或者增加程序空間。
如何除錯和匯編你的第一個PC x86匯編語言程序呢?
以下這些簡單的解釋可以讓一個匯編語言新手使用DEBUG:
0)在使用時,如何快速獲得debug的使用幫助呢。
1)讓我們開始工作吧,例如:顯示BIOS的日期。
2)在你的電腦的COMMANG.COM文件里搜尋"IBM"這幾個字符。
3) 一位十六進制數(shù)的運算。
4) 檢查 x86寄存器內(nèi)容。
5)我們來編寫我們的第一個用機械語言編寫的程序-打印一個字符。
6) 我們現(xiàn)在用匯編語言指令來做和例5一樣的事情。
7)現(xiàn)在,我們不但要編寫一個匯編程序,而且我們還要把它存盤。
8) 現(xiàn)在,我們試一試查看一個已經(jīng)編好的程序。
9)你可以用DEBUG的計算功能計算程序的長度。
10)另一種顯示在屏幕上字符串的方法。
11)讓我們試一試反復輸出。
12)我們現(xiàn)在把兩個程序連接起來。
13) 讓我們逐步運行這個剛剛修補的程序。
14)如果一開始的命令不是跳轉(zhuǎn)命令,那么可能就要用這種方法了。
以下所有的命令都是可以運行在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.
因為錯了所以它給你顯示一些提示。留意到最后一句了嗎?
現(xiàn)在我們再來試一試:
PROMPT> DEBUG<按回車> (注意, DEBUG程序的命令是在一條橫線"-"后出現(xiàn)的。)
-?<在出現(xiàn)的橫線后面輸入?再回車> (下面的內(nèi)容是按字母順序排列的)
(注意: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]
分配擴展內(nèi)存allocate expanded memory XA [#pages]
釋放擴展內(nèi)存deallocate expanded memory XD [handle]
map expanded memory pages XM [Lpage] [Ppage] [handle]
display expanded memory status XS
-q<按回車> (這是退出DEBUG回到DOS狀態(tài))This quits out of debug, returning to the DOS prompt)
Tested examples below walk the user thru the following debug examples:
在下面的例子里讀者必須明白以下幾條DEBUG命令。
-D 顯示一定范圍內(nèi)存的內(nèi)容Display the contents of an area of memory
-Q 退出DEBUG程序Quit the debug program
-S 搜尋Search for whatever
-H 十六進制的運算Hex arithmatic
-R 顯示或者改變一個或者多個寄存器的內(nèi)容Display or change the contents of one or more registers
-E 輸入數(shù)據(jù)進入內(nèi)存,在一個詳細的地址里Enter data into memory, beginning at a specific location
-G 運行現(xiàn)在在內(nèi)存里的程序。Go run the executable program in memory
-U 反匯編,把我們不認識的機械代碼變?yōu)槲覀兛梢哉J識匯編語言符號Unassemble machine code into symbolic code
-T 描述一條指令的用法。Trace the contents of one instruction
-P 進行或者執(zhí)行一個相關的指令Proceed, or execute a set of related instructions
-A 編譯,把匯編命令變?yōu)闄C械代碼Assemble symbolic instructions into machine code
-N 命名一個程序Name a program
-W 把一個已經(jīng)命名的程序?qū)戇M磁盤Write the named program onto disk
-L 把程序裝載進內(nèi)存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的日期?(譯者這里也不是很清楚所以請大家知道的也留言給斑竹,改正。譯者認為可能是內(nèi)存的真實物理地址。)
返回目錄
2)在你的電腦的COMMANG.COM文件里搜尋"IBM"這幾個字符
下面的"C:\Win95\"是根據(jù)每不電腦不同的。像譯者的電腦里就是"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>
(注意:搜尋是要區(qū)分大小寫的)
(你可以看到上面是沒有找到"IBM"的, 可以試一試"PATH" , "COMSPEC" , "COMMAND")
(注意: 這種方法用在查找加密資料和已被刪除的資料等方面時是十分有用的)
返回目錄
3) 一位十六進制數(shù)的運算:
PROMPT> DEBUG<按回車>
-H 9 1<按回車> (加減兩個十六進制的數(shù), 9h+1h=Ah & 9h-1h=8h)
結果是顯示: 000A 0008
-Q<按回車> (退出DEBUG)
C:\WINDOWS>debug
-h 9 1
000A 0008
-q
C:\WINDOWS>
返回目錄
4) 檢查x86寄存器內(nèi)容
PROMPT> DEBUG<按回車>
-R<按回車> (顯示x86寄存器內(nèi)容)
-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
下面是對寄存器的簡單介紹:
數(shù)據(jù)存儲器
在本類中,一般講的AH就是AX的前八位,AL就是AX的后八位,后面的以此類推。
AX Accumulator;作為累加器,所以它是算術運算的主要寄存器。另外所有的I/O指令都使用這一寄存器與外部設備傳送信息。
BX Base register;可以作為通用寄存器使用,此外在計算存儲器地址時,它經(jīng)常用作基地址寄存器。
CX Counting register;可以作為通用寄存器使用,此外在循環(huán)(LOOP)和串處理指令中作隱含的計數(shù)器。
DX Data register;可以作為通用寄存器使用,一般在作雙字長運算時,把DX和AX組合在一起存放一個雙字長數(shù),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 ;數(shù)據(jù)段寄存器,存放當前運行程序所用的數(shù)據(jù)
SS Battery segment register ;堆棧段寄存器,定義了堆棧所在區(qū)域
ES Extra segment register ;附加段寄存器,存放附加的數(shù)據(jù),是一個輔助性的數(shù)據(jù)區(qū),
控制寄存器
IP Next instruction pointer register;指令指針寄存器,它用來存放代碼段中的偏移地址,在程序運行的過程中,它始終指向下一條指令的首地址,它與CS寄存器聯(lián)用確定下一條指令的物理地址
F Flag register;標志寄存器 "NV UP EI PL NZ NA PO NC"就是了,也有人稱之為PSW Program Status Wold程序狀態(tài)寄存器
(這里有一點必須講明白的現(xiàn)在在,其實從奔騰開始這些寄存器(除了所有段寄存器,標志寄存器 )都是32位的。并且加多了兩個16位段寄存器FS,GS。dos下面看到這些寄存器是16位的。要看32位寄存器可以使用soft-ice。對于FS,GS的作用我也不是很清楚,希望有高手指點,謝謝。)
來自 紫色星云
狀態(tài) 離線 5)我們來編寫我們的第一個用機械語言編寫的程序-打印一個字符
(這里用機械語言的主要原因是考慮到有一些用戶不懂匯編命令,現(xiàn)在就要讓他有一個認識計算機程序?qū)嵸|(zhì)是一些數(shù)字)
PROMPT> DEBUG<按回車>
-E 100<按回車> (在偏移地址為100的地方輸入機械指令程序)
B4<按空格>02<按空格> (在AX寄存器的前八位存入02)
B2<按空格>41<按空格> (在DX寄存器的后八位存入41h,41h就是大寫A的ASCII碼,身邊有ASCII表的朋友可以對著表改改數(shù)字試一試)
CD<按空格>21<按空格> (當AH=02時這是DOS顯示輸出的中斷號)
CD<按空格>20<按回車> (退出DOS)
-G<按回車> (程序運行,并在屏幕上顯示出"A")
程序運行完以后你將看到"Program terminated normally"(程序正常結束了).
-U 100<按回車> (我們把它反匯編,就是把機械命令變?yōu)閰R編語言指令)
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<按回車> (執(zhí)行第一步操作... IP=>102h, AX=>0200h,指令指針寄存器指向下一條命令,AX的值被改變。
-T<按回車> (執(zhí)行第二步操作... IP=>104h, , DX=>0041h,指令指針寄存器指向下一條命令,DX的值被改變。
-P<按回車> (繼續(xù)執(zhí)行 INT 21,IP=>106h, AX=>02h,)
-P<按回車> (繼續(xù)執(zhí)行INT 20)
-Q<按回車> (退出DEBUG)
(注意:你必須小心使用"T".因為如果你在程序完結以后繼續(xù)執(zhí)行這條命令,因為我們無法預知下面的指令是什么,所以我們也無法預知它可能帶來的后果)
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) 我們現(xiàn)在用匯編語言指令來做和例5一樣的事情
PROMPT> DEBUG<按回車>
-A 100<按回車> (在偏移地址為100的地方輸入?yún)R編語言程序)
MOV AH,02<按回車> (選用DOS的02號功能調(diào)用,顯示輸出)
MOV DL,<按回車> (在DX寄存器的后八位存入41h,41h就是大寫A的ASCII碼,身邊有ASCII表的朋友可以對著表改改數(shù)字試一試)
INT 21<按回車> (當AH=02時這是DOS顯示輸出的中斷號,顯示"A")
INT 20<按回車> (退出DOS)
<按回車> (結束匯編語言編程狀態(tài),回到DEBUG命令狀態(tài))
-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