實驗二 彙編源程式編寫與彙編、除錯
;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], 4
mov byte ptr ds:[7], 4
mov ah, 4ch
int 21h
code ends
end
要求:
- 使用8086彙編程式編寫、彙編、連結、執行、除錯方法,對ex1.asm進行彙編、連結、執行,使用debug工具除錯可執行檔案。
使用masm、link對ex1.asm進行彙編、連結,得到可執行檔案ex1.exe,執行並觀察結果。
- 使用debug工具對程式進行除錯
- 使用debug載入可執行檔案ex1.exe後,使用d命令檢視程式段字首PSP所佔的256個位元組。
- 結合可執行檔案中暫存器CX的值,使用u命令對ex1.exe進行精確反彙編。
- 使用g命令執行到程式退出執行之前(即原始碼檔案中line16之前),觀察結果。
2. 實驗任務2 使用任意一款文字編輯器,編寫8086彙編源程式ex2.asm。原始碼如下: ; ex2.asm
assume cs:code
code segment
mov ax, 0b810h
mov 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 ends
end
要求:使用8086彙編程式編寫、彙編、連結、執行、除錯方法,對ex2.asm進行彙編、連結、執行,使用debug工具除錯可執行檔案。
- 使用masm、link對ex2.asm進行彙編、連結,得到可執行檔案ex2.exe,執行並觀察結果。
- 使用debug工具對程式進行除錯。
- 結合可執行檔案中暫存器CX的值,使用u命令對ex2.exe進行精確反彙編
- 靈活使用t命令、p命令、g命令,對ex2.exe進行除錯。(不一定要單步,有些地方可以用g命令,一次執行多行彙編指令)
注意:單步除錯時,對於迴圈指令loop,中斷指令int,使用t命令和p命令單步除錯的區別。
- 把ex2.asm中line9 mov cx, 4改成 mov cx, 8 ,儲存後重新彙編、連結、執行並觀察結果。
- 結合上述實驗和觀察,分析、對比ex2.asm和ex1.asm,它們實現的是否是相同的功能和效果?在 具體實現上有什麼不同?
3. 實驗任務3
綜合使用loop,[bx],編寫完整彙編程式,實現向記憶體b800:07b8開始的連續16個字單元重複填充字資料0237H。
要求:
- 編寫彙編源程式
- 給出執行結果截圖
如程式編寫正確,預期結果如圖所示。(執行前先使用 命令清屏,更便於觀察執行結果)
- 把填充的字資料,從0237H改成0239H,再次儲存後,彙編、連結、執行,觀察結果。
把填充的字資料,從0237H改成0437H,再次儲存後,彙編、連結、執行,觀察結果。
猜測並分析,這個字資料中高位位元組裡存放的是什麼資訊,低位位元組裡存放的是什麼資訊。
4. 實驗任務4- 編寫完整彙編源程式,實現向記憶體0:200~0:23F依次傳送資料0~63(3FH)。
- 必做
- 綜合使用[bx]和loop,編寫彙編源程式靈活使用debug的t命令、g命令、p命令除錯。在程式退出前,用d命令檢視0:200~0:23F,確認是否將0~3F傳送至此段記憶體區域。
- 選做*
- 利用棧的特性,綜合使用loop,push實現(限定僅使用8086中已學過指令實現),編寫源程式
- 靈活使用debug的t命令、g命令、p命令除錯。在程式退出前,用d命令檢視0:200~0:23F,確認是否將0~3F傳送至此段記憶體區域。
- 必做
Tips:
這道練習,本質上就是把一組連續的位元組資料(常數),送到指定的連續的位元組單元。如果利用棧實現,藉助push和loop實現連續入棧操作。需要注意:
- 初始時ss和sp的設定
- 8086的入棧操作,是從高地址單元→低地址單元方向的;
- 8086的入棧操作,只能以字為單元。但這裡是位元組資料,如何靈活處理?
5. 實驗任務5 教材實驗4(3)(P121)
Tips:這道練習,本質仍然是複製,只不過複製的是自身程式碼。填空的關鍵是,如何確定複製多少位元組。
6. 實驗任務6(選做*)
在linux環境下,編寫、彙編、執行、除錯一個32位的Intel風格的x86彙編程式。
第1步,使用vim或其它任意文字編輯器,編寫一個32位的Intel風格的x86彙編源程式example.asm。
; example.asm glogal _start section .data msg db "a simple test", 0xa len equ $ - msg section .text _start: mov eax, 4 mov ebx, 1 mov ecx, msg mov edx, len int 0x80 ; 呼叫linux下的int 0x80中斷的4號子功能,輸出字串 mov eax, 1 mov ebx, 0 int 0x80 ; 呼叫linux下的int 0x80中斷的1號子功能,退出
第2步,使用nasm,對example.asm進行彙編。
nasm -f elf32 example.asm
- 選項- f表示指定目標檔案格式。這裡指定目標檔案格式是elf32格式
如彙編成功,會生成目標檔案example.o。執行nasm命令後,可以使用ls命令檢視。
如果希望將來使用gdb工具對可執行檔案進行除錯,則使用nasm彙編時還需要增加一個選項-g,目的 是向目標檔案中增加符號和除錯的相關資訊。即:
nasm -f elf32 example.asm -g
第3步,使用ld,對example.o進行連結。
ld -m elf_i386 example.o -o example
- 選項-m指定模擬模式。這裡指定模擬intel 32位的模式。
- 選項-o用於指定可執行檔案的名稱。這裡指定生成的可執行檔名是example
如連結成功,會生成可執行檔案example。
第4步,執行可執行檔案example。
./example
執行後,可以在shell命令終端檢視返回值:
echo $?
顯示返回值0,對應原始碼檔案中line18暫存器ebx的值。
把example.asm中line18行中暫存器ebx的值改成別的數值,比如7。重新彙編、連結、執行。再次使用echo $?檢視返回值,觀察這次返回值是什麼。
注*:
1.彙編指令與硬體相關,因此,指令集有x86的彙編指令集,也有MIPS彙編指令集;書寫風格既有intel風格,也有AT&T風格。linux下預設是AT&T風格的。此外,可用的工具也種類繁多。這裡僅列出一個簡單示例,請根據個人情況自行探索實踐。
2.使用gdb除錯時,也需要掌握類似於debug下很多命令,比如list(檢視程式碼)、b(break,設定斷點)、r(run,執行)、檢視暫存器(info registers),等等。這裡沒有進一步提供使用gdb除錯的方法和步驟。請自行檢索相關工具文件,輔助嘗試。
四、實驗結論
1.實驗任務1
ex1.asm原始碼:
對原始碼進行彙編,連結,生成可執行檔案,執行結果為:
用debug對程式的執行過程進行跟蹤,用r命令檢視各暫存器的設定情況,根據CX的值用u命令進行反彙編,用d命令檢視程式段字首PSP所佔的256個位元組:
使用g命令執行到程式退出之前:
2.實驗任務2
ex2.asm原始碼:
使用masm,link對ex2.asm進行彙編,連結,執行,除錯:
使用debug工具對程式進行除錯,介乎額可執行檔案中暫存器CX的值,使用u命令進行精確返回百年,使用t命令,p命令,g命令,對ex2.exe進行除錯:
用g命令除錯到迴圈位置,緊接著用p命令直接執行完迴圈的內容,再用t去進行單步除錯,再遇到int 21時,用p命令退出該除錯:
用g命令除錯到迴圈位置,此時用t命令進行單步除錯,不會自動執行完迴圈的內容,而是一步步執行:
將ex2.asm中的mov cx,4改成mov cx,8,進行彙編,連結,執行,得到的結果為:
ex1.asm進行彙編,連結,執行的結果為:
顯示出的結果不相同,我將ex2.asm中的mov cx,8繼續改回到mov cx,4,進行彙編,連結,執行得到的結果為:
通過對比發現,ex2.asm和ex1.asm以及ex2.asm改變前後的結果不同可能是由於迴圈的次數不相同,mov cx,4所表示的意思是將迴圈進行4次,mov cx,8是將迴圈進行8次,一個得出的是4個圖案,另一個得出的是8個圖案,同樣的ex1.asm也迴圈了四次,因此出現的也是4個圖案。
3.實驗任務3
原始碼:
向記憶體b800:07b8開始的連續16個字單元重複填充字資料0237H:
向記憶體b800:07b8開始的連續16個字單元重複填充字資料0239H:
向記憶體b800:07b8開始的連續16個字單元重複填充字資料0437H:
猜想:字資料中高位位元組存放的是顏色,低位位元組存放的是內容
通過對比發現,當高位位元組改變時,執行結果的顏色進行了改變,當低位位元組改變時,執行結果的內容進行了改變。
4.實驗任務4
編寫完整彙編源程式,實現向記憶體0:200~0:23F依次傳送資料0~63(3FH)。
(1)必做:綜合使用[bx]和loop,編寫彙編源程式
程式碼:
對該源程式進行彙編,連結並用debug進行跟蹤除錯,用t命令,g命令,p命令進行除錯,並用d命令檢視是否將0~3F傳送到了0:200~0~23F中:
5.實驗任務5
原始碼為:
由於程式的起始地址由CS:IP指定,因此 mov ax,__處填寫CS,CS表示的是程式碼的段暫存器;
第九行填寫mov cx,16;
本題要求的是將mov ax,4c00h之前的程式碼段複製到0:200處,首先根據上述程式碼進行彙編,連結,並進行除錯
通過精確的反彙編可以發現,mov ax,4c00這條指令在076A:0017處,說明以上的指令是從076a:0~076a:0016,IP=IP+之前指令的位元組數為16h,因此填寫的內容為mov cx,16h.
用d命令檢視,發現已經將mov ax, 4c00h之前的指令複製到指定記憶體。