匯編語言程序設計 實驗2 匯編源程序編寫與匯編、調試
一、實驗目的
1. 理解並掌握匯編源程序組成與結構
2. 掌握匯編語言源程序編寫→匯編→鏈接→調試的工具和方法
3. 理解匯編源程序中地址表示、段寄存器的用法
4. 理解和掌握寄存器間接尋址方式[bx]
5. 通過匯編指令loop的使用理解編程語言中循環的本質
二、實驗內容及結果
(一)實驗任務一
使用任意一款文本編輯器,編寫8086匯編源程序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之前),觀察結果。
1、首先使用masm對*.asm文件進行編譯,生成包含機器代碼的目標文件(*.obj)
編譯后沒有問題(截圖中能看到提示說:0 Warning Errors和0 Severe Errors)這時候再返回到文件夾中就會發現多了一個.obj文件
對 *.obj 目標文件進行連接,得到可執行文件(.exe文件)。運行link后,首先顯示一些版本信息,然后提示輸入將要被連接的目標文件的名稱。注意,“[.OBJ]”提示我們,默認的文件擴展名是obj,**比如要連接的目標文件名是“xxx.obj”,只要在這里輸入“xxx”即可。**可如果文件不是以 obj 為擴展名,就要輸入它的全名。比如目標文件名為“ xxx.bin ”,就要輸入全名。
最后一行有提示信息:no stack segment,在網上查了意思,得知是:程序中沒有安排堆棧段。這個警告可以忽略,程序能夠運行,並且得到正確的結果。
在這里即可運行ex1.exe文件,得到結果:
2、使用debug工具對程序進行調試
首先使用d命令查看程序段前綴PSP所占的256個字節,結果如下圖所示:
再使用u命令對ex1.exe進行精確反匯編,首先可以借助r命令:
故u命令應為:
-u 076A:0 30
結果如下:
由上述結果可以觀察到,若要使用g命令執行到程序退出執行之前(即源碼文件中line16之前),代碼為:
-g 0028
結果如下所示:
(二)實驗任務二
使用任意一款文本編輯器,編寫8086匯編源程序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,它們實現的是否是相同的功能和效果?在具體實現上有什么不同?
1、與實驗任務一中的操作步驟類似,同樣可以對ex2.asm進行匯編、鏈接,得到可執行文件ex2.exe,結果如下:
2、使用debug工具對程序進行調試
首先可以結合可執行文件中寄存器CX的值,使用u命令對ex2.exe進行精確反匯編,和之前的操作步驟一樣,先使用r命令查看相關信息:
故可以得到u命令為:
-u 076A:0 001B
運行結果如下所示:
再可以靈活使用t命令、p命令、g命令,對ex2.exe進行調試,在這里關於如何使用這些命令,想法是:大部分命令都使用t命令單步執行來調試,但是遇到INT命令或者LOOP命令的時候,使用p命令來調試,因為INT命令類似於高級語言中的函數,如果這個時候還使用t命令的話,會相當於進入到函數內部,但是內部的調試過程不是我們想看到的,故在這里可以使用p命令來調試,而LOOP命令則是循環,我們不需要看到循環的過程,故也使用p命令。調試結果如下所示:
把ex2.asm中line9 mov cx, 4 改成 mov cx, 8 ,保存后重新匯編、鏈接、運行並觀察結果(由於前面的匯編鏈接運行過程存在重復內容,故這里不再贅述,只展示最后的結果)
小結:
對比ex2.asm和ex1.asm實現的是相同的功能,都是再屏幕上打印圖案。但是在具體實現上有所不同。具體體現在循環次數,結果也很好的顯示了這一效果,修改前是四個圖案,修改后則打印輸出了8個圖案。
(三)實驗任務三
綜合使用loop,[bx],編寫完整匯編程序,實現向內存b800:07b8開始的連續16個字單元重復填充字數據0237H。
要求:
編寫匯編源程序
給出運行結果截圖
代碼為:
assume cs:code code segment mov ax, 0b800h mov ds, ax mov bx, 07b8h mov cx, 000fh s: mov [bx], 0237h inc bx inc bx loop s mov ax, 4c00h int 21h code ends end
運行過程為:
最后的運行結果為:
可以看出,與預期結果完全一致。接下來把填充的字數據,從0237H 改成0239H,運行結果為:
把填充的字數據,從0237H 改成0437H后的結果為:
由上述結果對比可以看出:bx中前兩個字節控制顏色,后兩個字節控制形狀(不知道對不對0.0
(四)實驗任務四
編寫完整匯編源程序,實現向內存0:200~0:23F依次傳送數據0~63(3FH)。
1、必做部分
綜合使用[bx]和loop,編寫匯編源程序
靈活使用debug的t命令、g命令、p命令調試。在程序退出前,用d命令查看0:200~0:23F,確認是否將0~3F傳送至此段內存區域。
代碼如下所示:
assume cs:code code segment mov ax, 20h mov ds, ax mov bx, 0 mov cx, 40h mov al, 0 s:mov [bx], al inc al inc bx loop s mov ax, 4c00h int 21h code ends end
運行結果如下所示:
2、選做部分
利用棧的特性,綜合使用loop,push實現(限定僅使用8086中已學過指令實現),編寫源程序
靈活使用debug的t命令、g命令、p命令調試。在程序退出前,用d命令查看0:200~0:23F,確認是否將0~3F傳送至此段內存區域。
代碼如下所示:
assume cs:code code segment mov ax,0020h mov ss,ax mov sp,0040h mov bx,3f3eh mov cx,64 s: push bx sub bh,2 sub bl,2 loop s mov ax,4c00h int 21h code ends end
運行結果如下所示:
(五)實驗任務五
補全后的代碼為:
assume cs:code code segment mov ax,cs mov ds,ax mov ax,0020h mov es,ax mov bx,0 mov cx,0015h s:mov al,[bx] mov es:[bx],al inc bx loop s mov ax,4c00h int 21h code ends end
運行結果如下所示:
在這里,第一個空中:cs:ip表示cpu執行指令的地址。所有,只要mov ax,cs 就能把該程序在內存里的首地址mov到ax了。
第二個空:cx的值,也就是要求loop循環執行多少次。當程序運行到第8行,也就是mov cx,__ 時,cs:ip是該指令的地址。也就是說,從程序開始IP=0,到第8行,IP的值可以用來表示該程序指令占多少字節。
(六)實驗任務六
實驗過程中一直出現
error: parser: instruction expected
在互聯網上查了好多資料也不知道怎么解決,先放着等有時間再來看看
三、實驗總結
等搞定了任務六再來一起寫