[Assembly Language] 實驗2 彙編源程式編寫與彙編、除錯
Task1 編寫8086彙編源程式並進行彙編、連結、除錯
ex1.asm 檔案的內容如下:
;ex1.asm assume cs:code code segment mov ax, 0b810h mov ds, ax mov byte ptr ds:[0], 1 mov byte ptr ds:[1], 1 mov byte ptr ds:[2], 2 mov byte ptr ds:[3], 2 mov byte ptr ds:[4], 3 mov byte ptr ds:[5], 3 mov byte ptr ds:[6], 4mov byte ptr ds:[7], 4 mov ah, 4ch int 21h code ends end
在DOSBox中使用masm命令對ex1.asm檔案進行彙編,再對生成的.obj檔案使用link命令生成.exe檔案,具體指令為:
- masm ex1.asm;
- link ex1.obj;
(指令後面加分號可以略過一些細節引數的設定)
輸入ex1.exe執行,發現視窗上方出現蜜汁字元,出現的原因參考實驗1中相關內容。
在debug模式下,使用d命令檢視程式段字首PSP所佔的256個位元組。
根據暫存器CX中的值(CX=0031),得知彙編指令佔32位元組,使用命令-u 0 31,對exe檔案進行反彙編。
使用g命令執行該彙編程式,得到結果如下(與直接執行exe檔案效果相同):
(注:這裡可能會出現蜜汁字元不顯示的問題。原因是把字元打到指定位置後,由於-g命令的反饋資訊,介面向下滾動了3行,導致原來的字元也向上滾了3行,正好在介面外。通過檢視這些地址的值,發現已經被改變了,實際上這些值與介面中原字元對應位置的顯示內容有關。因此只要讓介面不滾動,就能完美地在指定位置輸出蜜汁字元。)
Task2編寫8086彙編源程式並進行彙編、連結、除錯(使用loop)
ex2.asm 檔案的內容如下:
; ex2.asm assume cs:code code segment mov ax, 0b810hmov ds, ax mov bx, 0 mov ax, 101h mov cx, 4 s: mov [bx], ax add bx, 2 add ax, 101h loop s mov ah, 4ch int 21h code endss end
使用masm、link命令彙編連結,執行ex2.exe,與ex1.exe的執行效果相同。
對ex2.exe使用debug工具,輸入u命令進行精確反彙編。
loop指令的地址為0016,輸入-g 16,顯示迴圈體第一次執行結果。之後每個步驟的顯示由於介面上滾,無法顯示,因此對原始碼修改記憶體的位置做出一點改動(初始DS改成B840),重新生成ex2.exe.
交替使用 -t 和 -g 16,顯示出每一步列印在螢幕上的字元(不對齊的原因 task1 中已經說了)。
排除除錯時螢幕滾動重新整理的原因,直接執行ex1.asm和ex2.asm所產生的exe的效果是一致的。
程式碼書寫上,ex1.asm採用順序結構,ex2.asm採用迴圈結構。後者對於開發者而言書寫的效率更高,但同時也讓機器執行了更多的指令,時間上並不優於前者。
Task3綜合使用loop, [bx],實現向記憶體b800:07b8開始的連續16個字單元重複填充字資料 0237H
編寫程式 ex3.asm 如下:
assume cs:code code segment mov ax, 0b800h mov ds, ax mov bx, 07b8h mov ax, 0237h mov cx, 16 m: mov [bx], ax add bx, 2 loop m mov ah, 4ch int 21h code ends end
使用 masm 和 link 對 ex3 進行彙編、連結,執行生成的exe檔案。
分別將填充的字資料改為 0239h 和 0437h,重新彙編連結過後,執行的結果如下:
猜測字資料的高位儲存的是字元的顏色,低位儲存的為字元的ASCII碼。
共256種顏色,其中後128種有閃爍效果。
共256種字元樣式,其中後128種為擴充套件ASCII碼。
Task4編寫完整彙編源程式,實現向記憶體0:200~0:23F依次傳送資料0~63(3FH)
(1)使用loop,[bx]實現
程式碼如下:
assume cs:code code segment mov ax, 0020h mov ds, ax mov bx, 0h mov cx, 40h m: mov [bx], bl add bx, 0001h loop m mov ah, 4ch int 21h code ends end
執行結果如下:
Task5 補全程式碼並除錯
該程式的功能是將 "mov ax, 4c00h" 之前的指令複製到 0:200 處,待補全程式碼如下:
1 assume cs:code 2 code segment 3 mov ax, _____ 4 mov ds, ax 5 6 mov ax, 0020h 7 mov es, ax 8 mov bx, 0 9 mov cs, _____ 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
填入程式碼為:
(1)mov ax, cs
(2)mov cx, 17h
填入後在 debug 模式下執行,使用 -d 命令分別檢視 0:200 和 076A:0 開始的資料。
該程式的功能是把從 076A:0 開始的若干位元組資料放入 0:200 開始的若干地址,寫入資料的量與具體填入的空有關。
如果一開始填入 mov ax, 076A,則有18h個位元組資料;填入 mov ax, cs,則有17h個位元組資料。原因是,mov 指令後如果是兩個暫存器佔用 2 個位元組,如果是一個暫存器和一個立即數佔用 3 個位元組。(通過觀察 -u 指令後每條指令所佔空間可以推斷出)
得知位元組數量最簡單的方法是,根據 CX 的值減去最後兩條指令佔的 5 個位元組(再填入到第二個空中)。