實驗2 彙編源程式編寫與彙編除錯.pdf
阿新 • • 發佈:2020-11-05
一、實驗結論
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使用masm、link對ex1.asm進行彙編、連結,得到可執行檔案ex1.exe,執行效果如下所示: 使用debug工具對程式ex1.exe進行除錯: 1)使用debug載入可執行檔案ex1.exe後,使用d命令檢視程式段字首PSP所佔的256個位元組,結果如下圖所示: 2)結合上圖確定暫存器CX的值為31h,即可使用u命令對ex1.exe進行精確反彙編,結果如下圖所示: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
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使用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的實現原理。12 add ax, 101h 13 loop s 14 15 mov ah, 4ch 16 int 21h 17 code ends 18 end
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
以上源程式執行的具體過程如下圖所示:
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(十進位制表示)填入第二空,下面進行程式程式碼的測試,測試過程如下圖所示: