【牛客7872 H 德邦王國】dfs全排列跑圖暴力衝過去
一、實驗內容
1. 實驗任務1
(1)使用8086彙編程式編寫、彙編、連結、執行、除錯方法,對ex1.asm進行彙編、連結、執行
- 使用任意一款文字編輯器,編寫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], 4 mov byte ptr ds:[7], 4 mov ah, 4ch int 21h code ends end
- 使用masm、link對ex1.asm進行彙編、連結,得到可執行檔案ex1.exe,執行並觀察結果。
- 此時可以看到經過masm、link對ex1.asm進行彙編、連結得到ex1.obj,ex1.exe檔案:
(2)使用debug工具對程式進行除錯
- 使用debug載入可執行檔案ex1.exe後,使用d命令檢視程式段字首PSP所佔的256個位元組。
- 結合可執行檔案中暫存器CX的值,使用u命令對ex1.exe進行精確反彙編
- 使用g命令執行到程式退出執行之前(即原始碼檔案中line16之前),觀察結果。
- 這裡可以看出資料改變了但是卻沒有改變成現象中的0 01 02..的形式,這裡通過檢視資料得知:
- 那是因為dosbox那個彩色線框的影響,它會在我們寫入視訊記憶體後重繪一遍彩色線框
- 對此我們需要在debug ex1.exe時先進行清屏cls操作,在進行接下來的步驟
2. 實驗任務2
(1)使用8086彙編程式編寫、彙編、連結、執行、除錯方法,對ex2.asm進行彙編、連結、執行
- 使用任意一款文字編輯器,編寫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
- 使用masm、link對ex2.asm進行彙編、連結,得到可執行檔案ex2.exe,執行並觀察結果。
(2)使用debug工具對程式進行除錯。
- 結合可執行檔案中暫存器CX的值,使用u命令對ex2.exe進行精確反彙編
- 靈活使用t命令、p命令、g命令,對ex2.exe進行除錯。
- (不一定要單步,有些地方可以用g命令,一次執行多行彙編指令)
- 注意:單步除錯時,對於迴圈指令loop, 中斷指令int,使用t命令和p命令單步除錯的區別。
- t命令除錯指令loop,中斷指令int,結果如下:
- p命令除錯指令loop和中斷指令int,結果如下:
- 結論:
T命令:單步執行,每次只執行一條程式碼語句,遇到子程式後進入子程式逐條執行指令;
P命令:類似T命令,若有子程式,直接執行完子程式全部指令而不是逐條執行指令,在遇到迴圈指令時,會直接執行至CX遞減至0;
G命令:多步執行,可以跟地址和斷點,即格式為 G[=address] [breakpoints],執行到[breakpoints]指定位置的指令後暫停,若不加引數則從當前IP執行到程式結束。
(3)把ex2.asm中 mov cx, 4 改成 mov cx, 8 ,儲存後重新彙編、連結、執行並觀察結果。
- 結合上述實驗和觀察,分析、對比ex2.asm和ex1.asm,它們實現的是否是相同的功能和效果?在
- 具體實現上有什麼不同?
ex1.exe結果如下:
改前ex2.exe結果如下:
改後ex2.exe結果如下:
- 結論:
1、對比ex2.asm和ex1.asm,它們實現的是相同的功能和效果,只是實驗二通過loop指令迴圈來實現,
實驗一則是一步一步賦值得到,所以相較於實驗一,實驗二的效率更高。
3. 實驗任務3
(1)綜合使用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 s: mov [bx],ax add bx,2 loop s mov ah,4ch int 21h code ends end
- 使用masm、link對ex2.asm進行彙編、連結,得到可執行檔案ex3.exe
- 執行ex3.exe,結果如下:
(2)把填充的字資料,從0237H 改成0239H,再次儲存後,彙編、連結、執行,觀察結果。
(3)把填充的字資料,從0237H 改成0437H,再次儲存後,彙編、連結、執行,觀察結果。
- 猜測與分析:
從實驗結果來看改變這個填充的字資料,從0237與0239的結果來看,結果沒有改變顏色而是改變了圖案,
而從0237與0437的結果來看,結果沒有改變圖案而是改變了顏色,所以可以猜想這個字資料高位元組確定顏色,
低位元組則確定圖案,同時檢視ascii表可以得出圖案是與ascii的值對應,如下圖:
4. 實驗任務4
(1)編寫完整彙編源程式,實現向記憶體0:200~0:23F依次傳送資料0~63(3FH)。
- 編寫彙編源程式:
;ex4.asm assume cs:code code segment mov ax,0020h mov ds,ax mov bx,0h mov ax,0h mov cx,64 s: mov [bx],ax add bx,1h add ax,1h loop s mov ah,4ch int 21h code ends end
- 使用masm、link對ex4.asm進行彙編、連結,得到可執行檔案ex4.exe
- 使用debug工具對程式進行除錯。
- 結合可執行檔案中暫存器CX的值,使用u命令對ex4.exe進行精確反彙編
-
靈活使用debug的t命令、g命令、p命令除錯。在程式退出前,用d命令檢視
0:200~0:23F,確認是否將0~3F傳送至此段記憶體區域。
- 結論:從實驗截圖可知資料被寫入到相應位置裡了
(2選做)利用棧的特性,綜合使用loop,push實現(限定僅使用8086中已學過指令實現),編
寫源程式
- 編寫彙編源程式:
;ex41.asm assume cs:code code segment mov ax,0020h mov ss,ax mov sp,0040h mov ax,3f00h mov cx,64 s: push ax inc sp dec ah loop s mov ax,4c00h int 21h code ends end
- 靈活使用debug的t命令、g命令、p命令除錯。用d命令檢視
0:200~0:23F,確認是否將0~3F傳送至此段記憶體區域。
5. 實驗任務5
(1)補全程式碼,並且除錯執行回答問題。
;ex5.asm assume cs:code code segment mov ax,cs mov ds,ax mov ax,0020h mov es,ax mov bx,0 mov cx,17h s: mov al,[bx] mov es:[bx],al inc bx loop s mov ax,4c00h int 21h code ends end
填空依據:
第一空:程式要求把程式碼“movax,4c00h”之前的指令複製到記憶體,所以要使段地址指向程式碼開始的地方
也就是cs指向的地址。
第二空:複製的指令是到程式碼“movax,4c00h”之前的指令,通過指令u可以看出指令是從0~17h結束,
所以填寫17h
- 使用masm、link對ex4.asm進行彙編、連結,得到可執行檔案ex4.exe
- 使用debug工具對程式進行除錯。
二、實驗總結
-
在dosbox的虛擬DOS環境下使用masm和link工具對.asm的彙編原始碼檔案進行彙編、連結生成EXE可執行檔案的具體操作步驟。
-
t命令,p命令,g命令的使用,及瞭解它們之間的區別:
-
T命令:單步執行,每次只執行一條程式碼語句,遇到子程式後進入子程式逐條執行指令;
-
P命令:類似T命令,若有子程式,直接執行完子程式全部指令而不是逐條執行指令,在遇到迴圈指令時,會直接執行至CX遞減至0;
-
G命令:多步執行,可以跟地址和斷點,即格式為 G[=address] [breakpoints],執行到[breakpoints]指定位置的指令後暫停,若不加引數則從當前IP執行到程式結束。
-
段暫存器DS, SS, ES, CS的瞭解與使用
-
迴圈指令loop的使用:指令的功能是 dec cx(計數暫存器),迴圈指令執行為cx減為0時停止。這裡要注意的是在debug中cx預設存放的是mov ah,4c00h之前指令總的位元組數。所以使用它當迴圈計數前要記得重新賦值。
- 在dosbox的虛擬DOS環境下在實驗過程中向視訊記憶體區改變資料不成功問題:對此是因為那可能是因為dosbox頁面輪轉了一次,使之前改變的記憶體資料又被覆蓋了,解決方法cls清屏一下,只要保證頁面一直在當前頁面就行。對比下面兩張圖可以看出,在開始頁面可以看到改變的記憶體資料與圖案,而當指令過多,頁面移動後圖案消失,同時資料被覆蓋。