四、實驗結論
2. 實驗任務2
- PC機主板上的ROM中有一個生產時期,在內存FFF00H ~ FFFFFH的某幾個單元中,請找到這個生產時期,並試圖修改它。
- 在debug中,使用d命令查看生產日期。
- 使用e命令修改生產時期所在的內存單元,修改后,再次使用d命令查看。
結論:不可修改,因為該段內存是ROM的內存單元,只能讀,不能修改。
- 在debug中,使用e命令,向內存單元填寫數據。
b800:0開始的內存單元開始,依次寫入十六進制數據04 03,重復寫5次。
- 在debug中,使用f命令,向內存單元批量填寫數據。
修改內存數據后效果截圖:

(1) 單步執行,在執行push指令和pop指令時,觀察並記錄棧頂偏移地址的寄存器sp值的變化情況。

- 填空
1 -a 2 mov ax, 20 3 mov ds, ax 4 mov ss, ax 5 mov sp, 30 6 push [0] ; 執行后,寄存器(sp) = 002E 7 push [2] ; 執行后,寄存器(sp) = 002C 8 push [4] ; 執行后,寄存器(sp) = 002A 9 push [6] ; 執行后,寄存器(sp) = 0028 10 pop [6] ; 執行后,寄存器(sp) = 002A 11 pop [4] ; 執行后,寄存器(sp) = 002C 12 pop [2] ; 執行后,寄存器(sp) = 002E 13 pop [0] ; 執行后,寄存器(sp) = 0030
- 回答問題
問題1:題目要求是把00220H ~ 0022fH用作棧空間。指令 mov ss, ax 和 mov sp, 30 執行后,棧頂的邏輯地址和物理地址分別是?
棧頂邏輯地址:0020:0030
物理地址:00230H
問題2:單步調試到匯編指令 push [6] 執行結束, pop [6] 執行之前,使用 d 20:20 2f 查看此時棧空間數據,給出實驗截圖。
問題3 :匯編指令 pop [0] 執行結束后,使用d命令 d 20:0 7 查看此時數據空間內的數據是否有變化。給出實驗截圖。
問題4:如果把最后四條指令改成截圖中的順序, pop [6] 指令執行結束后,使用d命令 d 20:0 7查看此時數據空間內的數據是否有變化。給出實驗截圖。
5. 實驗任務5
- 回答問題1和問題2。
問題1:使用t命令單步執行 mov ss, ax 時,是單步執行完這一條指令就暫停了嗎?后面的指令 movsp, 30 是什么時候執行的?
使用t命令單步執行 mov ss, ax 時,不是單步執行完這一步就暫停。Debug的T命令在執行修改寄存器SS的指令時,下一條指令也緊接着被執行。
問題2:根據匯編指令,前三條指令執行后,00220H ~ 0022fH被設置為棧空間。並且,初始時,已通過f命令將初始棧空間全部填充為0。觀察單步調試時,棧空間00220H ~ 0022fH內存單元值的變化,特別是圖示中黃色下划線表示出的數據值。根據實驗觀察,嘗試思考和分析原因。
原因:通過查閱資料,在一篇博客中提到棧的分配會多分配5個字的單元。一般,堆棧中存放的多是各個寄存器的值以保持程序環境。而T命令的具體壓棧流程為PUSHF,PUSH CS,PUSH IP,PUSH BP,PUSH AX。所以在T命令單步執行時,將此時CS IP的值存入了棧中。
6. 實驗任務6
1 assume cs:code 2 3 code segment 4 start: 5 mov cx, 10 6 mov dl, '0' 7 s: mov ah, 2 8 int 21h 9 add dl, 1 10 loop s 11 12 mov ah, 4ch 13 int 21h 14 code ends 15 end start
- 使用masm、link,匯編、鏈接,得到可執行文件task6.exe。運行程序。結合程序運行結果,理解程序功能。
- 使用debug工具,調試task6.exe。根據第4章所學知識,任何可執行程序在執行時,都有一個引導程序負責將其加載到內存,並將CPU控制權移交給它,也即將CS:IP指向可執行程序中第一條機器指令。在加載可執行程序時,可執行前面512字節是程序段前綴PSP(Program Segment Prefix),用於記錄程序一些相關信息。
- 在debug中,使用d命令,查看task6.exe的程序段前綴,觀察這256個字節的內容,驗證前兩個字節是否是CD 20。
assume cs:code code segment start: mov cx, 10 mov dl, '0' s: mov ah, 2 int 21h add dl, 1 loop s mov ah, 4ch int 21h code ends end start
對程序匯編、鏈接過程截圖如下:

查看程序段前綴及運行結果截圖如下:

驗證得到PSP的首兩個字節是CD 20。
7. 實驗任務
1 assume cs:code 2 code segment 3 mov ax, ① 4 mov ds, ax 5 mov ax, 0020h 6 mov es, ax 7 mov bx, 0 8 mov cx, ② 9 s: mov al, [bx] 10 mov es:[bx], al 11 inc bx 12 loop s 13 14 mov ax, 4c00h 15 int 21h 16 code ends 17 end
- 給出補全后的完整源碼。說明程序中兩個空填寫的依據。
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
填寫依據:
①程序代碼段地址為cs,所以將cs指向地址賦值給寄存器ax,再通過ax存入數據段地址ds。
②寄存器cx中存放的是可執行文件長度,因此可以先隨便賦值給cx,進行debug,然后通過r命令得到cx為21h,而要求復制mov ax, 4c00h 之前的指令,因此cx值21h-5h=17h。
- 在debug中調試,使用g命令將程序執行到 loop s 之后、 mov ax, 4c00h 之前,然后,使用u命令對0:200開始的內存單元反匯編,確認是否把task7.asm中line3-line12的代碼復制到了目標內存空間。給出使用g命令運行到指定點和使用u命令反匯編0:200到復制代碼長度這一段內存空間的截圖。
驗證代碼截圖如下:

五、實驗總結:
①邏輯地址=段地址:偏移地址
物理地址=段地址*16+偏移地址
②編寫匯編源程序時,默認是十進制。對於十六進制,需手動添加H。如: mov ax, 30H。而debug工具中默認是十六進制。
③使用debug調試時,調試的必須是可執行文件,並且要帶擴展名。即: debug ××.exe。
④使用debug ××.exe調試時,首次進入調試界面時,寄存器CX中存放的是可執行文件長度。可以通過u命令,結合CS、IP、CX的值,對 *.exe文件反匯編,得到匯編源程序。
⑤程序加載后,ds中存放着程序所在內存區的段地址,這個內存區的偏移地址為0,所以程序所在內存區的地址為ds:0;而這個內存區的前256個字節存放的PSP,用來和程序通信;這個256字節之后的空間存放程序。
另外CS=DS+10h,這里的10h的內容就是PSP(程序段前綴),也就是說程序中最為核心的指令部分從CS:IP指向的內存單元開始。
⑥將匯編語言源程序經過匯編(編譯)后生成的二進制的機器指令代碼,用U指令變為助記符形式的匯編指令,稱為反匯編。
