★
DEBUG是為匯編語言設計的一種高度工具,它通過單步、設置斷點等方式為匯編語言程序員提供了非常有效的調試手段。一、DEBUG程序的調用在DOS的提示符下,可鍵入命令: C:\DEBUG [D:][PATH][FILENAME[.EXT]][PARM1][PARM2] 其中,文件名是被調試文件的名字。如用戶鍵入文件,則DEBUG將指定的文件裝入存儲器中,用戶可對其進行調試。如果未鍵入文件名,則用戶可以用當前存儲器的內容工作,或者用DEBUG命令N和L把需要的文件裝入存儲器后再進行調試。命令中的D指定驅動器PATH為路徑,PARM1和PARM2則為運行被調試文件時所需要的命令參數。在DEBUG程序調入后,將出現提示符,此時就可用DEBUG命令來調試程序。二、DEBUG的主要命令1、顯示存儲單元的命令D(DUMP),格式為:_D[address]或_D[range]例如,按指定范圍顯示存儲單元內容的方法為:-d100 12018E4: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.718E4:0120 8B其中0100至0120是DEBUG顯示的單元內容,左邊用十六進制表示每個字節,右邊用ASCII字符表示每個字節,·表示不可顯示的字符。這里沒有指定段地址,D命令自動顯示DS段的內容。如果只指定首地址,則顯示從首地址開始的80個字節的內容。如果完全沒有指定地址,則顯示上一個D命令顯示的 后一個單元后的內容。2、修改存儲單元內容的命令有兩種。·輸入命令E(ENTER),有兩種格式如下:第一種格式可以用給定的內容表來替代指定范圍的存儲單元內容。命令格式為:-E address [list]例如,-E DS:100 F3'XYZ'8D其中F3,'X','Y','Z'和各占一個字節,該命令可以用這五個字節來替代存儲單元DS:0100到0104的原先的內容。第二種格式則是采用逐個單元相繼修改的方法。命令格式為:-E address例如,-E DS:100則可能顯示為:18E4:0100 89.-如果需要把該單元的內容修改為78,則用戶可以直接鍵入78,再按"空格"鍵可接著顯示下一個單元的內容,如下:18E4:0100 89.78 1B.-這樣,用戶可以不斷修改相繼單元的內容,直到用ENTER鍵結束該命令為止。·填寫命令F(FILL),其格式為:-F range list例如:-F 4BA:0100 5 F3'XYZ'8D使04BA:0100~0104單元包含指定的五個字節的內容。如果list中的字節數超過指定的范圍,則忽略超過的項;如果list的字節數小于指定的范圍,則重復使用list填入,直到填滿指定的所有單元為止。3)檢查和修改寄存器內容的命令R(register),它有三種格式如下:·顯示CPU內所有寄存器內容和標志位狀態,其格式為:-R例如,-rAX=0000 BX=0000 CX=010A DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000DS=18E4 ES=18E4 SS=18E4 CS=18E4 IP=0100 NV UP DI PL NZ NA PO NC18E4:0100 C70604023801 MOV WORD PTR [0204],0138 DS:0204=0000·顯示和修改某個寄存器內容,其格式為:-R register name例如,鍵入-R AX系統將響應如下:AX F1F4:即AX寄存器的當前內容為F1F4,如不修改則按ENTER鍵,否則,可鍵入欲修改的內容,如: -R bxBX 0369:059F則把BX寄存器的內容修改為059F。·顯示和修改標志位狀態,命令格式為:-RF系統將響應,如:OV DN EI NG ZR AC PE CY-此時,如不修改其內容可按ENTER鍵,否則,可鍵入欲修改的內容,如:OV DN EI NG ZR AC PE CY-PONZDINV即可,可見鍵入的順序可以是任意的。4)運行命令G,其格式為:-G[=address1][address2[address3…]]其中,地址1指定了運行的起始地址,如不指定則從當前的CS:IP開始運行。后面的地址均為斷點地址,當指令執行到斷點時,就停止執行并顯示當前所有寄存器及標志位的內容,和下一條將要執行的指令。5)跟蹤命令T(Trace),有兩種格式:·逐條指令跟蹤-T [=address]從指定地址起執行一條指令后停下來,顯示所有寄存器內容及標志位的值。如未指定地址則從當前的CS:IP開始執行。·多條指令跟蹤-T [=address][value]從指定地址起執行n條指令后停下來,n由value指定。6)匯編命令A(Assemble),其格式為:-A[address]該命令允許鍵入匯編語言語句,并能把它們匯編成機器代碼,相繼地存放在從指定地址開始的存儲區中。必須注意:DEBUG把鍵入的數字均看成十六進制數,所以如要鍵入十進制數,則其后應加以說明,如100D。7)反匯編命令U(Unassemble)有兩種格式。·從指定地址開始,反匯編32個字節,其格式為:-U[address]例如:-u10018E4:0100 C70604023801 MOV WORD PTR[0204],013818E4:0106 C70606020002 MOV WORD PTR[0206],020018E4:010C C70606020202 MOV WORD PTR[0208],020218E4:0112 BBO4O2 MOV BX,020418E4:0115 E80200 CALL 011A18E4:0118 CD20 INT 2018E4:011A 50 PUSH AX18E4:011B 51 PUSH CX18E4:011C 56 PUSH SI18E4:011D 57 PUSH DI18E4:011E 8B37 MOV SI,[BX]如果地址被省略,則從上一個U命令的 后一條指令的下一個單元開始顯示32個字節。·對指定范圍內的存儲單元進行反匯編,格式為:-U[range]例如:-u100 10c18E4:0100 C70604023801 MOV WORD PTR[0204],013818E4:0106 C70606020002 MOV WORD PTR[0206],020018E4:010C C70606020202 MOV WORD PTR[0208],0202或-u100 112 18E4:0100 C70604023801 MOV WORD PTR[0204],013818E4:0106 C70606020002 MOV WORD PTR[0206],020018E4: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裝入存儲器。
裝入命令(Load),有兩種功能。·把磁盤上指定扇區范圍的內容裝入到存儲器從指定地址開始的區域中。其格式為:-L[address[drive sector sector]·裝入指定文件,其格式為:-L[address]此命令裝入已在CS:5CH中格式化了文件控制塊所指定的文件。如未指定地址,則裝入CS:0100開始的存儲區中。10)寫命令W(Write),有兩種功能。·把數據寫入磁盤的指定扇區。其格式為:-W address drive sector sector·把數據寫入指定的文件中。其格式為:-W[address]此命令把指定的存儲區中的數據寫入由CS:5CH處的文件控制塊所指定的文件中。如未指定地址則數據從CS:0100開始。要寫入文件的字節數應先放入BX和CX中。11)退出DEBUG命令Q(Quit),其格式為:-Q它退出DEBUG,返回DOS。本命令并無存盤功能,如需存盤應先使用W命令。
問題:初學者問一個低級問題,執行debug-a后,如果有一行輸入錯誤,如何更改這一行?
回答:加入進行如下輸入:D:\PWIN95\Desktop>debug-a2129:0100movax,2002129:0103movbx,2002129:0106movcx,2002129:0109此時,發現movbx,200一句錯誤,應為movbx,20,可以敲回車返回"-"狀態,然后輸入:-a1032129:0103movbx,20如果多或者少若干行,不必重新輸入,可以用M命令移動后面的程序來去掉或者增加程序空間。
如何除錯和匯編你的第一個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 bythe 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:008D12A7:04F712A7:387012A7:38BE12A7:38DD-S 0 L FFFF "PATH"12A7:38AD12A7:CCB712A7:CF55-S 0 L FFFF "COMSPEC"12A7:38D412A7:3A4D12A7: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 1000A 0008-qC:\WINDOWS>4) 檢查x86寄存器內容
PROMPT> DEBUG<按回車>-R<按回車> (顯示x86寄存器內容)-Q<按回車> (退出DEBUG)
C:\WINDOWS>debug-RAX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000DS=127C ES=127C SS=127C CS=127C IP=0100 NV UP EI PL NZ NA PO NC127C: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 100127C:0100 B4.B4 02.02 B2.B2 41.41 CD.CD 21.21 CD.CD 20.20-GAProgram terminated normally-U 100127C:0100 B402 MOV AH,02127C:0102 B241 MOV DL,41127C:0104 CD21 INT 21127C:0106 CD20 INT 20127C:0108 C706F1E30900 MOV WORD PTR [E3F1],0009127C:010E EB59 JMP 0169127C:0110 57 PUSH DI127C:0111 BFF1E3 MOV DI,E3F1127C:0114 8BDF MOV BX,DI127C:0116 06 PUSH ES127C:0117 0E PUSH CS127C:0118 07 POP ES127C:0119 32D2 XOR DL,DL127C:011B EB34 JMP 0151127C:011D 006B12 ADD [BP+DI+12],CH-RAX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000DS=127C ES=127C SS=127C CS=127C IP=0100 NV UP EI PL NZ NA PO NC127C:0100 B402 MOV AH,02-T
AX=0200 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000DS=127C ES=127C SS=127C CS=127C IP=0102 NV UP EI PL NZ NA PO NC127C:0102 B241 MOV DL,41-T
AX=0200 BX=0000 CX=0000 DX=0041 SP=FFEE BP=0000 SI=0000 DI=0000DS=127C ES=127C SS=127C CS=127C IP=0104 NV UP EI PL NZ NA PO NC127C:0104 CD21 INT 21-PAAX=0241 BX=0000 CX=0000 DX=0041 SP=FFEE BP=0000 SI=0000 DI=0000DS=127C ES=127C SS=127C CS=127C IP=0106 NV UP EI PL NZ NA PO NC127C: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 100127C:0100 MOV AH,02127C:0102 MOV DL,41127C:0104 INT 21127C:0106 INT 20127C:0108-GAProgram 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 100127C:0100 MOV AH,02127C:0102 MOV DL,41127C:0104 INT 21127C:0106 MOV DL,42127C:0108 INT 21127C:010A MOV DL,43127C:010C INT 21127C:010E INT 20127C:0110-RAX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000DS=127C ES=127C SS=127C CS=127C IP=0100 NV UP EI PL NZ NA PO NC127C:0100 B402 MOV AH,02-R BXBX 0000:-R CXCX 0000:0010-N PRINTABC.COM-WWriting 00010 bytes-QC:\WINDOWS>DIR PRINTABC.COMVolume in drive C has no labelVolume Serial Number is 28FB-70BADirectory of C:\WINDOWSPRINTABC COM 16 03-21-01 11:02 PRINTABC.COM1 file(s) 16 bytes0 dir(s) 557,711,360 bytes freeC:\WINDOWS>PRINTABCABCC:\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 1012A4:0100 B402 MOV AH,0212A4:0102 B241 MOV DL,4112A4:0104 CD21 INT 2112A4:0106 B242 MOV DL,4212A4:0108 CD21 INT 2112A4:010A B243 MOV DL,4312A4:010C CD21 INT 2112A4:010E CD20 INT 20-RAX=0000 BX=0000 CX=0010 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000DS=12A4 ES=12A4 SS=12A4 CS=12A4 IP=0100 NV UP EI PL NZ NA PO NC12A4:0100 B402 MOV AH,02-GABCProgram terminated normally9)你可以用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 1000210 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 200127C:0200 2C.48 D5.65 BA.6C FF.6C FF.6F B8.2C 00.57 AE.6F127C:0208 CD.72 2F.6C 3C.64 00.24 C3.-D 200127C: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..!_^s127C: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... u127C: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 100127C:0100 MOV AH,09127C:0102 MOV DX,0200127C:0105 INT 21127C:0107 INT 20127C:0109-GHello,WorldProgram terminated normally-D200127C: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..!_^s127C: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... u127C: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 100030B 010B-R BXBX 0000:-R CXCX 0000:010B-N PRINTHW.COM-WWriting 0010B bytes-QC:\WINDOWS>DIR PRINTHW.COMVolume in drive C has no labelVolume Serial Number is 28FB-70BADirectory of C:\WINDOWSPRINTHW COM 267 03-22-01 11:53 PRINTHW.COM1 file(s) 267 bytes0 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,09BA0002 MOV DX,0200E90301 JMP 020B90 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"
設為首頁 |
添加收藏 |
合作加盟|
友情鏈接
湖南省陽光電子技術學校常年開設:手機維修培訓、家電維修培訓、電腦維修培訓、網絡工程師培訓、電工培訓、焊工培訓--面向全國招生。安置就業。考試合格頒發全國通用權威證書。電話:0731-85579057,網站:
http://www.hnygpx.com