1. 程式人生 > 實用技巧 >實驗2 彙編源程式編寫與彙編除錯.pdf

實驗2 彙編源程式編寫與彙編除錯.pdf

一、實驗結論

1. 實驗任務1

使用任意一款文字編輯器,編寫8086彙編源程式ex1.asm。原始碼如下:
 1 ;ex1.asm
 2 assume cs:code
 3 code segment
 4     mov ax, 0b810h
 5     mov ds, ax
 6     
 7     mov byte ptr ds:[0], 1h
 8     mov byte ptr ds:[1], 1h
 9     mov byte ptr ds:[2], 2h
10     mov byte ptr ds:[3], 2h
11     mov byte ptr ds:[4], 3h
12 mov byte ptr ds:[5], 3h 13 mov byte ptr ds:[6], 4h 14 mov byte ptr ds:[7], 4h 15 16 mov ah, 4ch 17 int 21h 18 code ends 19 end
使用masm、link對ex1.asm進行彙編、連結,得到可執行檔案ex1.exe,執行效果如下所示:

使用debug工具對程式ex1.exe進行除錯: 1)使用debug載入可執行檔案ex1.exe後,使用d命令檢視程式段字首PSP所佔的256個位元組,結果如下圖所示:

2)結合上圖確定暫存器CX的值為31h,即可使用u命令對ex1.exe進行精確反彙編,結果如下圖所示:

3)使用g命令執行到程式退出執行之前(即原始碼檔案中line16之前),結合上圖所示,只需執行到偏移地址為 2dh之前,執行結果如下圖所示:

2. 實驗任務2

使用任意一款文字編輯器,編寫8086彙編源程式ex2.asm。原始碼如下:
 1 ;ex2.asm
 2 assume cs:code
 3 code segment
 4     mov ax, 0b810h
 5     mov ds, ax
 6 
 7     mov bx, 0h
 8     mov ax, 0101h
 9     mov cx, 4h
10 s:  mov [bx], ax
11     add bx, 2h
12 add ax, 101h 13 loop s 14 15 mov ah, 4ch 16 int 21h 17 code ends 18 end
使用masm、link對ex2.asm進行彙編、連結,得到可執行檔案ex2.exe,執行效果如下所示:

使用debug工具對程式ex2.exe進行除錯: 1)結合可執行檔案中暫存器CX的值,使用u命令對ex2.exe進行精確反彙編,執行結果如下圖所示:

2)靈活使用 t命令、p命令、g命令,對ex2.exe進行除錯。(不一定要單步,有些地方可以用g命令,一次執行多行彙編指令),執行結果如下圖所示: * 首先使用 g命令執行到圖中紅色標記處,執行結果如下圖所示:

* 接下來使用 t命令來一步一步檢視迴圈體所實現的功能,一次迴圈的效果如下圖所示:

分析一次迴圈體所作的工作:將 ax暫存器的值賦給記憶體地址為 ds:[bx] 的記憶體單元,一次賦值一個字; 其中 bx從 0h開始每次自增 2h,而 ax從 0101h開始每次自增0101h。迴圈一共執行四次,那麼彙總一下, 迴圈所做的功能:將 0101 0202 0303 0404這些資料依次寫入記憶體地址為 B810:0000 ~B810:0007的記憶體單元中。 下面驗證分析是否正確:

3)將ex2.asm中line9 mov cx, 4 改成 mov cx, 8並把檔案重新命名為ex3.asm,儲存後重新彙編、連結、執行,執行結果如下圖所示:

由於改變cx 暫存器的值即改變 loop迴圈指令執行的次數,同時其他初始資料未作相關變動,可以分析此彙編程式碼實現的功能: 將 0101 0202 0303 0404 0505 0606 0707 0808 這些資料依次寫入記憶體地址為 B810:0000 ~B810:000f 的記憶體單元中。 下面驗證分析是否正確:

4)思考:結合上述實驗和觀察,分析、對比ex2.asm和ex1.asm,它們實現的是否是相同的功能和效果?在具體實現上有什麼不同? 答:從實現功能以及程式執行的結果來看,ex1.asm 和 ex2.asm 其實是一致的,都是向記憶體地址為 B810:0000~B810:0007的連續    記憶體單元寫入相同的資料;但就具體實現而言,ex1.asm 的實現方式就是直接使用mov指令依次寫入資料,如果要寫入的資料    足夠多,那會導致彙編程式碼繁雜冗餘;由於寫入的資料都是有規律的,同時也是向一段連續的記憶體地址寫入資料,那麼此時就    可以藉助迴圈即 loop指令來防止程式碼冗餘而實現的功能都是一致的,這便是ex2.asm的實現原理。

3. 實驗任務3

任務:綜合使用 loop,[bx],編寫完整彙編程式,實現向記憶體b800:07b8開始的連續16個字單元重複填充字資料0237H。 實現以上任務的原始碼如下所示:
 1 ;ex4.asm
 2 assume cs:code
 3 code segment
 4     mov ax, 0b800h
 5     mov ds, ax
 6     mov bx, 07b8h
 7     mov ax, 0237h
 8     mov cx, 16h
 9 
10 x:  mov [bx], ax
11     add bx, 2h
12     loop x
13     
14     mov ah, 4ch
15     int 21h
16 code ends
17 end
使用masm、link對ex4.asm進行彙編、連結,得到可執行檔案ex4.exe,執行效果如下所示:

執行 ex4.exe,執行效果如下圖所示:

* 把填充的字資料,從0237H 改成 0239H,再次儲存後,彙編、連結、執行,執行效果如下圖所示:

* 把填充的字資料,從0237H 改成0437H,再次儲存後,彙編、連結、執行,執行效果如下圖所示:

猜測並分析,這個字資料中高位位元組裡存放的是什麼資訊,低位位元組裡存放的是什麼資訊? 答:列出所有寫入的資料以及顯示結果:    A.資料: 0237H;結果:綠色的“ ? ”    B.資料: 0239H;結果:綠色的“ 9 ”    C.資料: 0437H;結果:紅色的“ ? ”   結合以上列出的資料以及結果,可以知道在儲存這些字的記憶體地址中,高位位元組儲存的是字元的顏色,   低位位元組儲存的是字元的二進位制表示。

4. 實驗任務4

任務:編寫完整彙編源程式,實現向記憶體0:200~0:23F依次傳送資料0~63(3FH) 1)綜合使用[bx]loop,編寫彙編源程式實現,源程式如下:
 1 assume cs:code
 2 code segment
 3     mov ax, 0
 4     mov ds, ax
 5     mov bx, 200h
 6     mov ax, 0
 7     mov cx, 40h
 8 
 9 s:  mov [bx] ,al
10     inc ax
11     inc bx
12     loop s
13 
14     mov ax, 4c00h
15     int 21h
16 code ends
17 end

以上源程式執行的具體過程如下圖所示:


2)利用棧的特性,綜合使用looppush(限定僅使用8086中已學過指令實現)編寫源程式,源程式如下所示:
 1 assume cs:code
 2 code segment
 3     mov ax, 0
 4     mov ss, ax
 5     mov sp, 0240h
 6     mov ah, 3fh
 7 
 8 s: push ax
 9     dec ah
10     inc sp
11     loop s
12 
13     mov ah, 4ch
14     int 21h
15 code ends
16 end

以上源程式執行的具體過程如下圖所示:

5. 實驗任務5

任務:下面的程式功能是將“ mov ax, 4c00h ”之前的指令複製到記憶體 0:200 處,補全程式。上機除錯,跟蹤執行結果。 實現以上任務的原始碼如下:(其中帶下劃線的是需要我們補全的程式碼)
 1 assume cs:code
 2 code segment
 3     mov ax, _cs_
 4     mov ds, ax
 5     mov ax, 0020h
 6     mov es, ax
 7     mov bx, 0
 8     mov cx, _17h_
 9 
10 s:  mov al,[bx]
11     mov es:[bx], al
12     inc bx
13     loop s
14 
15     mov ax, 4c00h
16     int 21h
17 code ends
18 end
從彙編程式碼整體觀之,要想完成第一個空的填寫,就需要明白 ds暫存器應該指向哪裡,由於本任務是想要 彙編實現程式碼自己複製自己到記憶體的另一塊,那麼很明顯該複製的資料應該來自程式碼本身所對應的機器碼。 所以此時 ds暫存器的值應該等於 cs暫存器的值,這樣才可以從記憶體單元取出機器碼複製到另外一個記憶體塊; 接下來需要完成第二空,我們知道 cx暫存器是用來控制程式迴圈的次數。從迴圈體中可以看出,每次迴圈 都取出一個位元組的機器碼並且複製到另一塊記憶體單元上,所以我們必須得知道“ mov ax, 4c00h ”之前的指令 對應的機器碼要佔用多少位元組,這樣才能控制迴圈次數。遺憾的是,我們並不知道各類機器碼所佔用的位元組數。 為了獲取“ mov ax, 4c00h ”之前的指令對應的機器碼佔用位元組數,我們隨意使用一個數據(假設使用“ 1122h ”) 將第二空填上,讓其通過編譯,連結,然後使用 debug工具來反編譯彙編程式碼,這樣就可以獲取確實的機器碼 位元組數了,具體執行如下圖所示:

根據上圖的測試結果,我們將迴圈次數 17h 或者23(十進位制表示)填入第二空,下面進行程式程式碼的測試,測試過程如下圖所示: