1. 程式人生 > >彙編——實驗3

彙編——實驗3

該實驗主要是對於組合語言源程式的編寫以及除錯執行。終於寫了第一個彙編程式啦!

一、實驗內容

(在除錯之前,根據老師之前在課上的演示,通過dir命令檢視是否有相關檔案。)

練習1:編寫彙編源程式t1.asm,對源程式 t1.asm 進行彙編、連線、執行、除錯 。

1.在記事本里寫入t1.asm的內容,並將txt字尾名修改為asm。

2.通過masm,link等命令進行彙編,連線,執行。如圖,程式的執行結果在螢幕上出現了36。

(同時,在c:\masm5 中出現了相關的t1.obj,t1.exe檔案:)

3.將 line4和line9種暫存器dl 的值分別修改為 0~9 中任何一個數字,重新彙編→ 連線→執行,觀察結果的變化。

結果如圖,修改line4和line9中暫存器的值後,螢幕上輸出28。

4.用debug對生成的可執行檔案 t1.exe 進行除錯。

顯然,如圖,CS中的值為15DF,DS的值為15CF,它們之間滿足(CS)=(DS)+10H的關係。CX中的值為16H,即程式的長度為16H。同時檢視PSP的頭兩個位元組為CD 20,在這裡用d命令檢視記憶體中程式段字首的內容,從ds:0到ds:f,這是由於PSP在記憶體中佔256個位元組,故而偏移地址從0h-fh。

接下來使用u命令對該可執行檔案進行反彙編。注意此時反彙編的地址範圍根據CX暫存器的值來確定。在該實驗中CX中的值為16H,即程式的長度為16H。

接下來使用t命令和p命令單步除錯。

 

 

練習2:1.編寫彙編源程式t2.asm,對源程式 t2.asm 進行彙編、連線、執行、除錯 。

對t2.asm進行彙編、連線後,得到t2.exe可執行檔案。在清屏之後執行t2.exe,螢幕左上方出現如圖所示的house數字36!

 

2.重新開啟t2.asm,嘗試將原始碼中line7的0433h→0432h, line10 的 0436h→0439h, 然後重新彙編、連線,得到可執行檔案 t2.exe。使用 cls 命令清 屏後,再次觀察程式執行結果。

如上圖所示,在螢幕的左上方出現了藍色的數字36!

二、延伸思考與分析

1、練習2和實驗1的實驗任務4有著相似的結果,輸出的字元有顏色,還可以做相應的改變。在實驗1的任務4中,修改的是段地址從B810H開始的記憶體單元的內容。在這裡段地址是從B800H開始的記憶體單元。它們都是8086CPU機記憶體地址空間分配中的視訊記憶體地址空間部分。所以直接在螢幕上會有所顯示結果。

assume cs:code
code segment
             mov ax,0b800h
             mov ds,ax     //將b800h送入ds暫存器中,作為接下來要操作的記憶體單元的段地址
             
             mov bx,0
             mov [bx],word ptr 0433h  //將0433h依次寫入b800:0記憶體單元中

             add bx,2
             mov [bx],word ptr 0436h  //將0436h依次寫入b800:2記憶體單元中

             mov ax,4c00h   
             int 21h  //實現程式返回功能
code ends
end

在執行完t2.exe檔案後,b800:0-b800:3記憶體單元中的值本應變為 33h,04h,36h,04h,可是由於修改的是視訊記憶體地址空間,如實驗1的任務4,會在螢幕上出現一些很神奇的變化。所以我做了以下嘗試,在debug環境下,直接修改b800:0-b800:3記憶體單元的值為33h,04h,36h,04h,觀察是否會發生變化。

經過實驗,我的想法是偏移地址為0,2,4等的記憶體單元中的是值(是顯示出字元的ASCII碼值)的作用是在螢幕上顯示相應的字元。偏移地址為1,3,5等的記憶體單元中的值是修改字元的顏色。

2.比較練習1和練習2,結果同樣是在螢幕上顯示相關字元,兩者的方式卻不同。練習1中是通過呼叫相關的函式去實現完成它,而練習2則是巧妙地在視訊記憶體的記憶體單元中寫入相應字元。

三、總結與體會

1.通過課上的學習以及多次實驗,掌握瞭如何在螢幕上輸出字元的源程式的幾種方式。(其實就是將該字元的ASCII碼送入相應的暫存器中的過程)

assume cs:code
code segment
              mov ah,2
              mov dl,3
              add dl,30h   //在螢幕上顯示'3'這一字元
              int 21h

              mov ah,4ch
              int 21h
code ends
end

(其中line4和line5的作用是將dl中的資料修改為51,即3的ASCII碼。)

 或者

assume cs:code
code segment
             mov ah,2
             mov dl,'3'  //在螢幕上顯示'3'這一字元
             int 21h

             mov ah,4ch
             int 21h
code ends
end

若在line4後面加一行add dl 30h,則dl的值變為99,即在螢幕上顯示ASCII碼為99的字元即'c',經過上機實驗得以驗證。

或者

如練習2中程式碼一樣,向視訊記憶體中寫入相應資料。

2.在練習1的單步除錯時,發現在第一次用p命令除錯int 21h後,al中的值發生了變化,變為33h,同樣的,在第二次除錯完int 21h後,al的值變為36h,發現兩次al中的值和當時dl中的值一樣,很神奇!同時通過查閱資料還發現,int 21h指令有一系列的使用方法和相關說明(https://blog.csdn.net/RichieVoe/article/details/8235873)。

3.在練習2中,將0433h送入記憶體單元地址為b800:0中時,發現剛開始直接寫 mov [bx],0433h會出現error,一開始還以為不能直接將常數送入記憶體單元中,可是查了相關資料發現並沒有這一規定,再次翻閱課件時才發現問題所在,原來將常數送入記憶體單元時,由於是常數,無法確定是以位元組還是字還是雙字等為單位,故而記憶體單元無法分配空間,所以必須明確指出常數是以什麼為單位。應寫為 mov [bx],word ptr 0433h(由於0433h是2個位元組,故而不能用Byte直接作為該單位)。

總之,每次實驗雖然中途會出各種各樣的小錯誤,但是每次都有所收穫。我會努力學習更多知識,來慢慢揭開彙編的神奇面紗~