1. 程式人生 > >實驗 5 編寫、調試具有多個段的程序

實驗 5 編寫、調試具有多個段的程序

再次 分析 文件 循環 嘗試 tac 直接 出了 mov

一、實驗目的

1. 理解和掌握將數據、代碼、棧放入不同段的程序的編寫和調試

2. 理解具有多個段的匯編源程序對應的目標程序執行時,內存分配方式

二、實驗準備

1. 結合第 6 章教材和課件,復習第 6 章內容

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

三、實驗內容

實驗任務(1)

下載課程公郵中的程序框架放入,masm.exe,link.exe同文件夾下,用DS BOX掛載到masm文件夾後

使用之前寫好的process.bat文件簡化編譯,連接,執行操作。

技術分享圖片

順利執行,下面對ex5_1.exe debug。

技術分享圖片

使用r命令查看各寄存器的值,下面我們要精確反匯編程序段,首先通過r命令可以看出cx=0042,

即這段程序所占的字節數是42h,但這還包括數據段和棧段,數據段有8個數據,16個字節,即

10h,棧段也是16個字節,即10h。所以代碼段長度為42-20=22h,CS:IP = 076C:0000,所以若要精確反匯編

,應該是u 0000 0021(註:代碼段,棧段,數據段均是從0開始的)。成功反匯編代碼段。

題目要求的是程序返回前,即 mov ax,4c00 int 21前,根據反匯編結果可知,因執行到CS:001d前,使用

g命令達到這一效果。

已經可以看出CPU執行程序,程序返回前,cs=076c,ss=076b,ds=076a.

接下來需要查看數據段,已知數據段長16個字節,使用d命令查看內存中的數據 d 0 f(註:代碼段,棧段,數據段均是從0開始的)

可以看出,程序返回前的數據段並沒有改變(讀數據時註意是小端法存儲的)。

技術分享圖片

使用g命令執行完程序,程序加載後,可以看出DS = CS-2,SS=CS-1;

技術分享圖片

根據實驗結果完成了書中填空。

實驗任務(2)

前期步驟同(1)

技術分享圖片

同實驗(1),首先通過r命令可以看出cx=0042,即這段程序所占的字節數是42h,但這還包括數據段和棧段,數據段有2個數據,4個字節,棧段也是2個字節。

所以代碼段長度為42-8=34h,CS:IP = 076C:0000,所以若要精確反匯編

,應該是u 0000 0033(註:代碼段,棧段,數據段均是從0開始的)。但這裏我卻並沒有做到成功反匯編,顯然我們所給反匯編範圍大了

技術分享圖片

通過查看源代碼,給出猜測,雖然棧段和數據段都只給出了4個字節,但從第13行代碼看出

,這裏設sp = 16,棧頂設為了16,也就是說這裏的棧仍然是16個字節的,盡管沒有填滿,所以情況應該和

實驗(1)是一樣的,當然這只是我的猜測

技術分享圖片

精確反匯編的結果與實驗(1)一樣

技術分享圖片

題目要求的是程序返回前,即 mov ax,4c00 int 21前,根據反匯編結果可知,因執行到CS:001d前,使用

g命令達到這一效果。

已經可以看出CPU執行程序,程序返回前,cs=076c,ss=076b,ds=076a.

接下來需要查看數據段,已知數據段長4個字節,使用d命令查看內存中的數據 d 0 3(註:代碼段,棧段,數據段均是從0開始的)

可以看出,程序返回前的數據段並沒有改變(讀數據時註意是小端法存儲的)。

技術分享圖片

使用g命令執行完程序,程序加載後,可以看出DS = CS-2,SS=CS-1;

這裏的情況和實驗(1)是一樣的

考慮對於如下定義的段:

name segment

...

name ends

通過查閱資料得知

如果段中數據占N個字節,則程序加載後,該段實際占有的空間為 [(N+15)/16]*16。

數據段都是以16個字節對齊,不足16字節按16字節算,這也解釋了對於實驗任務(2)我的

疑問。

根據實驗結果完成書中填空

技術分享圖片

實驗任務(3)

與實驗任務(1)(2)相同,前面的步驟在這裏就省略截圖分析了,直接從debug後開始

技術分享圖片

這裏的精確反匯編又出現了問題,根據之前的實驗總結,應該是CX = 44-10-10=24h,

所以應該是 u 0 23進行精確反匯編,但這裏卻還是應該 u 0 21。原因不得而知。

技術分享圖片

修改後精確反匯編

技術分享圖片

已經可以看出CPU執行程序,程序返回前,cs=076a,ss=076e,ds=076d.

接下來需要查看數據段,已知數據段長4個字節,使用d命令查看內存中的數據 d 0 3(註:代碼段,棧段,數據段均是從0開始的)

可以看出,程序返回前的數據段並沒有改變(讀數據時註意是小端法存儲的)。

技術分享圖片

使用g命令執行完程序,程序加載後,可以看出DS = CS+3,SS=CS+4;

根據實驗結果完成書中填空

技術分享圖片

實驗任務(4)

如果將(1),(2),(3)題中的最後一條偽指令“end start”改為“end”(也就是說,不指明程序的入口個),則哪個程序仍然可以正確執行?請說明原因。

對三個程序內容進行修改編譯連接執行後

技術分享圖片

對第一個程序的反匯編結果,可以發現該程序已經沒有辦法正確執行

技術分享圖片

程序2也是無法正確執行

技術分享圖片

程序3可以正確執行

因為如果沒有end start就會默認以IP=0開始執行,而不是從start開始執行。

而實驗內容(3)的data和stack都在code之後,所以IP本來就為0,可以正確執行。

實驗任務(5)

(1) 匯編程序源代碼

補全代碼如下:

技術分享圖片

分析:編寫code代碼,將a段b段中的數據依次相加,將結果存在c段中。

bx用於偏移量,初始置顯然為0,dx為求和寄存器初始值也是0,cx用於設置循環次數,這裏有a,b中均有8個字

,所以循環次數也就是8次。

循環體部分:每次將a段中和b段中內容依次加到寄存器dx中,最後將結果存到c段中。

這裏需要註意,循環體開頭部分每次都要將用於求和的寄存器bx置為0,否則上次的結果會接著累加。

偏移量bx每次增加一次,大體步驟就是這樣,具體細節在這裏就不做過多的闡述。

(2) 在 debug 中調試程序截圖,截圖中包括如下信息:

① 在實現數據相加前,邏輯段 c 的 8 個字節

技術分享圖片

進入debug,然後查看寄存器,精確反匯編(CX-10h-10h-10h=29h),u 0 28

技術分享圖片

根據精確反匯編結果,執行到循環體外,使用d命令查看數據段內容,發現並沒有做到預期,

但查看棧段內容時,發現第二行到第四行顯示的內存符合預期,原因不得而知。

② 執行完實現加運算的代碼後,邏輯段 c 的 8 個字節

技術分享圖片

使用g命令執行完成後,發現用d命令查看數據段內存內容仍然不符合預期,但棧段內存內容

符合,第四行確實是前兩行相加的結果。

根據①和②的調試,證實了程序確實正確的實現數據相加。

實驗任務(6)

(1) 匯編程序源代碼

補全代碼如下:

技術分享圖片

分析:編寫code段中的代碼,用push指令將a段中的前8個字型數據,逆序存儲b段中。

需要逆序存儲,自然的便想到了棧段,這裏需要設一個棧段,需要將b段前8個字數據逆序存儲,

8個字數據即16個字節,棧頂SP = 16 =10h,棧底為SS = SP+1.

這裏只要設置8次循環,將a段中前8個字型數據push到棧中,即實現了題目要求。

(2) debug 中調試程序截圖,截圖中包括如下信息:

技術分享圖片

進入debug,使用r命令進行查看,精確反匯編(CX-20h-10h=1fh)u 0 1e

成功精確反匯編。

① 在 push 操作執行前,查看邏輯段 b 8 個字單元信息截圖

技術分享圖片

根據反匯編結果,使用g命令執行到push操作前,用d命令查看內存中內容,長度為a段的

32(20h)個字節加上b段16(10h)個字節,d ds:0 29.

可以看出b段8個字全是0.

② 執行 push 操作,然後再次查看邏輯段 b 8 個子單元信息截圖

技術分享圖片

使用g命令執行完成後,用d命令查看,發現b的8個字單元為a段前8個字節的逆序.

根據①和②的調試,驗證程序確實正確的實現題目要求。

五、總結與體會

1.通過此次實驗理解和掌握將數據、代碼、棧放入不同段的程序的編寫和調試

理解具有多個段的匯編源程序對應的目標程序執行時,內存分配方式。

2.我們開始逐漸進入到匯編編程中,匯編也並不是很枯燥的,在實驗過程中只有不斷的探索嘗試才能真正

體會匯編的樂趣。

實驗 5 編寫、調試具有多個段的程序