1. 程式人生 > >組合語言實驗五

組合語言實驗五

 

  • 實驗任務一

1.利用debug載入、跟蹤程式

(1)先利用r命令來檢視各個暫存器的值

(2)從cx中可知道程式的長度,用cx中的值減去20h(資料段和棧段已分配的空間)得到程式碼段的長度,用u命令精確反彙編

(3)先執行到000D之前,看看ds是否已成功指向資料段

(4)從上圖可以看到ds已指向資料段,然後我們接著執行到程式返回前,即到001D之前,再檢視一次資料段的內容

(5)從上圖可以看到,資料段沒有發生變化

2.書上的問題解答:

(1)程式返回前,data段中的資料為 23 01 56 04 89 07 BC 0A-EF 0D ED 0F BA 0C 87 09

(2)程式返回前,CS=076C,SS=076B,DS=076A

(3)設程式載入後,code段的段地址為X,則data段的段地址為X-2,stack段的段地址為X-1

  • 實驗任務二

 1.利用debug載入、跟蹤程式

(1)先利用r命令檢視各個暫存器的值

(2)從上圖的cx我們可以看到,cx的值與任務一的一樣。雖然任務二隻定義了兩個字資料的資料段和兩個字型資料當棧空間,但實際上在記憶體分配上還是給它們16個位元組的空間,於是我用u命令精確反彙編一下

(3)再用g命令執行到000D以前,看看ds是否指向資料段data

(4)從上圖看出ds已指向資料段data,再執行到程式返回前,看看資料段data的變化

(5)從上圖看出,資料段沒有變化

2.書上問題的解答:

(1)程式返回前,data段中的資料為 23 01 56 04

(2)程式返回前,CS=076C,SS=076B,DS=076A

(3)設程式載入後,code段的段地址為X,則code段的段地址為X-2,stack段的段地址為X-1

(4)對於如下定義的段,若段中的資料佔N個位元組,則程式載入後,該段實際佔有的空間為(N/16+1)*16(即資料的分配是以16個位元組為單位的)

name segment
:
name ends
  • 實驗任務三

 1..利用debug載入、跟蹤程式

(1)同樣用r檢視各個暫存器的值,並用u精確反彙編

(2)用g命令執行至000D之前,看看ds是否指向資料段data

(3)從上圖可以看出,ds指向了資料段data,接著執行到程式返回前,再檢視資料段data的值

(4)從上圖可以看到,資料段中的值沒有變化

2.書上問題的解答:

(1)程式返回前,data段中的資料為 23 01 56 04

(2)程式返回前,CS=076A,SS=076E,DS=076D

(3)設程式載入後,code段的段地址為X,則data段的段地址為X+3,stack段的段地址為X+4

  • 實驗任務四

1.以實驗任務三為例,刪除end後面的start,執行看結果,步驟與上面一致

(通過上面的截圖,我們可以發現與任務三中的結果完全一致,也就是說,除去了end後面的start,程式仍然能正確執行)

2.再以任務二為例,刪去end後面的start,再執行檢視結果,步驟與上面一致

(上圖注意:此時精確反彙編的不同,變成以cs為段地址,以20h為偏移地址

(雖然執行的過程有所差異,但是執行後的結果是一致的,即去掉了end後面的start,也能正確執行)

3.書上問題解答:

 (1)比較上面的過程與結果,我認為這三個程式去掉了end後面的start都能正確執行。唯一的不同點在於,雖然去掉了start,cs:ip的值會指向程式起始位置的段地址,但實際上隨著程式的執行,最後總會將程式碼段執行完;而加上start之後,cs:ip的值一開始就直接指向了我們的程式碼段,更方便我們的操作。

  • 實驗任務五

 1.填寫的程式程式碼如下:

start:   mov ax,a
         mov ss,ax ;利用段暫存器ss指向a段的起始位置

         mov ax,b
         mov es,ax ;利用段暫存器es指向b段的起始位置

         mov ax,c
         mov ds,ax ;利用段暫存器ds指向c段的起始位置

         mov bx,0
         mov cx,8
    s:   mov al,ss:[bx]
         mov [bx],al  ;將a段資料複製到c段中
         mov al,es:[bx]
         add [bx],al  ;將b段資料與c段的資料相加,結果儲存在c段中
         inc bx       ;由於定義的是位元組資料,所以只需要將bx加一
         loop s

         mov ax,4c00h
         int 21h

2.利用debug跟蹤、執行

(1)先用r檢視各個暫存器的值,再用u反彙編

(2)先執行到000A之前,可以檢視a段和b段的資料,a段由ss段暫存器指向,b段由es段暫存器指向

(3)再執行到0022之前,看看c段中的結果

(4)從上圖可以看到,實現了將a段和b段中資料的依次相加

3.補充:做完該實驗才看到老師的tips,於是決定按照分段利用es的方法,再完成一次

(1)程式碼如下:

start: mov ax,c
         mov ds,ax ;利用段暫存器ds指向c段起始地址
         mov ax,a
         mov es,ax ;先利用段暫存器es指向a段起始地址

         mov bx,0
         mov cx,8
   s:   mov al,es:[bx] 
         mov [bx],al     ;做一個將a段資料複製到c段中的迴圈
         inc bx
         loop s

         mov ax,b
         mov es,ax  ;再利用段暫存器es指向b段起始地址

         mov bx,0
         mov cx,8
   s0:  mov al,es:[bx]
         add [bx],al       ;再做一個將b段資料加到c段中的迴圈
         inc bx
         loop s0

         mov ax,4c00h
         int 21h

(2)利用debug跟蹤、執行

(先執行到000A之前,看看a段的資料)

(再執行到0018之前,看看c段的資料)

(接著執行到001D之前,檢視b段的資料)

(最後執行到程式返回前,看看c段中的結果)

(從上圖可以看到,實現了a、b段資料的依次相加

  • 實驗任務六

 1.填寫的程式碼如下:

start: mov ax,a
         mov ds,ax ;利用段暫存器ds指向a段

         mov ax,b
         mov ss,ax   ;利用段暫存器ss指向b段,讓b段作為棧空間
         mov sp,16  ;初始化棧頂

         mov bx,0
         mov cx,8
     s:  push [bx]
         add bx,2
         loop s

         mov ax,4c00h
         int 21h

2.利用debug跟蹤、執行

(1)用r檢視各個暫存器的值,再用u反彙編

(2)先執行到0005,檢視a段資料

(3)最後執行到程式返回前,看看b段中的資料

(從上圖可以看到,實現了將a段中的前8個字型資料逆序儲存到b段中

  • 總結與體會

1.通過本次實驗熟悉並掌握了編寫、除錯具有多個段的程式,收穫非常大

2.我上網搜尋了一下關於實驗任務二中提到的 “段中資料大小與實際佔用空間” 這部分的內容:

3.關於實驗任務一、二、三中都提到的,code段、data段、stack段的段地址的關係:

    對於任務一和二,data段定義用了16個位元組(0~f),stack段定義用了16個位元組(10~2f),所以段地址會與程式碼段相差2和1;而在任務三中,程式碼段佔了32個位元組,所以後面定義的data的段地址和stack的段地址會與程式碼段相差3和4。

4.關於實驗任務五,在我一開始寫的程式碼中,除了ds和es之外,我還運用了ss段暫存器,這樣就只需要執行一次迴圈,最後也同樣達到了目的。因為我覺得當ss不用來定義棧空間時,它就只是一個普通的段暫存器,所以一樣可以派上用場。