組合語言實驗五
-
實驗任務一
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不用來定義棧空間時,它就只是一個普通的段暫存器,所以一樣可以派上用場。