1. 程式人生 > 實用技巧 >【牛客7872 H 德邦王國】dfs全排列跑圖暴力衝過去

【牛客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清屏一下,只要保證頁面一直在當前頁面就行。對比下面兩張圖可以看出,在開始頁面可以看到改變的記憶體資料與圖案,而當指令過多,頁面移動後圖案消失,同時資料被覆蓋。