1. 程式人生 > 實用技巧 >洛谷 P2659 美麗的序列

洛谷 P2659 美麗的序列

一、實驗目的

1. 理解並掌握彙編源程式組成與結構

2. 掌握組合語言源程式編寫→彙編→連結→除錯的工具和方法

3. 理解彙編源程式中地址表示、段暫存器的用法

4. 理解和掌握暫存器間接定址方式[bx]

5. 通過彙編指令loop的使用理解程式語言中迴圈的本質

二、實驗準備

1. 學習/複習第5章使用[bx]和loop實現迴圈的程式設計應用示例(教材5.5節,5.8節)

2. 複習第3章「棧」的知識

3. 結合第4章課件,複習完整彙編源程式編寫→彙編→連線→執行→除錯的方法

4. 複習8086彙編中記憶體單元地址的表示,以及段暫存器DS, SS, ES, CS的用途

三、實驗內容

1. 實驗任務1

使用任意一款文字編輯器,編寫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
要求:使用8086彙編程式編寫、彙編、連結、執行、除錯方法,對ex1.asm進行彙編、連結、執行,使用debug工具除錯可執行檔案。    • 使用masm、link對ex1.asm進行彙編、連結,得到可執行檔案ex1.exe,執行並觀察結果。    •使用debug工具對程式進行除錯    •使用debug載入可執行檔案ex1.exe後使用d命令檢視程式段字首PSP所佔的256個字 節。     •結合可執行檔案中暫存器CX的值,使用u命令對ex1.exe進行精確反彙編     •使用g命令執行到程式退出執行之前(即原始碼檔案中line16之前),觀察結果。 1)編輯源程式 2)編譯,連線 3)執行

4)d命令檢視程式段字首PSP所佔的256個位元組:程式的實體地址為SA*16+0+256=SA*16+16*16+0=(SA+16)*16+0,由這段可知段地址和偏移地址表示的為:SA+10H:0,所以PSP地址為CS-10H:IP。

5)使用u命令對ex1.exe進行精確反彙編(應為CX中值為0031),所以此時反彙編的記憶體單元從76A:0-76A:30

6)g命令執行到程式退出執行之前

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,它們實現的是否是相同的功能和效果?在具體實現上有什麼不同 1)使用masm、link對ex2.asm進行彙編、連結,得到可執行檔案ex2.exe,執行並觀察結果。 執行 出現四個圖案 2)使用debug工具對程式進行除錯。 使用u命令對ex2.exe進行精確反彙編 靈活使用t命令、p命令、g命令,對ex2.exe進行除錯。 使用p命令和g命令 t命令單步執行(部分截圖)
注意:t命令在遇到loop指令時會執行每一條迴圈指令,而p命令遇到迴圈指令時,會直接執行至CX遞減至0。 把ex2.asm中line9 mov cx, 4 改成 mov cx, 8 ,儲存後重新彙編、連結、執行並觀察結果。 出現八個圖案 結合上述實驗和觀察,分析、對比ex2.asm和ex1.asm,它們實現的是否是相同的功能和效果?在 具體實現上有什麼不同? ex1.asm採用順序結構,將指令一條條送入記憶體;ex2.asm採用loop迴圈結構縮短了重複程式碼,對於開發者而言程式碼書寫效率高。

3. 實驗任務3

綜合使用loop,[bx],編寫完整彙編程式,實現向記憶體b800:07b8開始的連續16個字單元重複填充字資料 0237H

編寫彙編源程式

1)執行

2)把填充的字資料,從0237H 改成0239H,再次儲存後,彙編、連結、執行,觀察結果。

3)把填充的字資料,從0237H 改成0437H,再次儲存後,彙編、連結、執行,觀察結果。

4)猜測並分析,這個字資料中高位位元組裡存放的是什麼資訊,低位位元組裡存放的是什麼資訊。

猜測:高位元組存放顏色資訊,低位元組存放內容資訊

4.實驗任務4 編寫完整彙編源程式,實現向記憶體0:200~0:23F依次傳送資料0~63(3FH)。

1)綜合使用[bx]和loop,編寫彙編源程式

2)靈活使用debug的t命令、g命令、p命令除錯。在程式退出前,用d命令檢視 0:200~0:23F,確認是否將0~3F傳送至此段記憶體區域。

使用d命令檢視:

5. 實驗任務5

將“mov ax,4c00h"之前的指令複製到記憶體0:200處,補全程式

;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

題目的要求是把程式碼段內的指令當作資料,複製到目的地址,所以,源資料段ds和程式碼段cs相同,所以第一空填 cs

第二空可以隨機填入一個十六進位制數,對源程式進行反彙編,得到指令總長度為001B,其中mov ax,4C00h之前的指令共佔位元組為0000-0016共17h個位元組,所以要完成複製需要執行mov es:[bx],al指令共17h次,所以CX的值應當設為17h.

cx確定後,對源程式進行單步執行,通過debug命令觀察,發現0:200-0:217的內容以及完成複製。

1)複製的是什麼,從哪裡到哪裡

題目的要求是把程式碼段內的指令當作資料,複製到目的地址,所以,源資料段ds和程式碼段cs相同,即複製位元組資料,從cs程式碼段到ds資料段,即0:200處

2)複製的是什麼,有多少個位元組,如何知道要複製的位元組數量

cx的值是loop迴圈的次數,而程式段的長度決定了迴圈寫入的次數,所以cx的值為程式段的長度。

可以用r命令檢視一開始cx的值,再用u命令反彙編。