實驗任務一
將下面的程序編譯、鏈接,用debug加載、跟蹤,然后回答問題。
1 assume cs:code, ds:data, ss:stack 2 data segment 3 dw 0123h, 0456h, 0789h, 0abch, 0defh, 0fedh, 0cbah, 0987h 4 data ends 5 6 stack segment 7 dw 0, 0, 0, 0, 0, 0, 0, 0 8 stack ends 9 10 code segment 11 start: mov ax,stack 12 mov ss, ax 13 mov sp,16 14 15 mov ax, data 16 mov ds, ax 17 18 push ds:[0] 19 push ds:[2] 20 pop ds:[2] 21 pop ds:[0] 22 23 mov ax,4c00h 24 int 21h 25 26 code ends 27 end start
①CPU執行程序,程序返回前,data段中的數據是多少?
②CPU執行程序,程序返回前,CS=____,SS=____,DS=____。
③設程序加載后,code段的段地址為X,則data段的段地址為____,stack段的段地址為____。
實現:
將代碼編譯、連接后,用debug工具調試:
①可以發現,data段的數據在執行程序后,程序返回前並未改變,仍是原始數據。
②從圖中可以看出,CPU執行程序,程序返回前,CS=076C,SS=076B,DS=076A。
③進一步可以發現,若code段的段地址為X,則data段的段地址為X-2,stack段的段地址為X-1。
實驗任務二
將下面的程序編譯、鏈接,用debug加載、跟蹤,然后回答問題。
1 assume cs:code, ds:data, ss:stack 2 data segment 3 dw 0123h, 0456h 4 data ends 5 6 stack segment 7 dw 0, 0 8 stack ends 9 10 code segment 11 start: mov ax,stack 12 mov ss, ax 13 mov sp,16 14 15 mov ax, data 16 mov ds, ax 17 18 push ds:[0] 19 push ds:[2] 20 pop ds:[2] 21 pop ds:[0] 22 23 mov ax,4c00h 24 int 21h 25 26 code ends 27 end start
①CPU執行程序,程序返回前,data段中的數據是多少?
②CPU執行程序,程序返回前,CS=____,SS=____,DS=____。
③設程序加載后,code段的段地址為X,則data段的段地址為____,stack段的段地址為____。
④對於如下定義的段:
name segment
...
name ends
如果段中的數據占N個字節,則程序加載后,該段實際占有的空間為____.
實現:
將代碼編譯、連接后,用debug工具調試:
①與(1)的結果一樣,data段的數據在執行程序后,程序返回前仍未改變,仍是原始數據。
②從圖中可以看出,CPU執行程序,程序返回前,CS=076C,SS=076B,DS=076A。
③與(1)的結果一致,若code段的段地址為X,則data段的段地址為X-2,stack段的段地址為X-1。
④對比(1)(2)可以發現,(1)中data段數據有16個字節,占用了16個字節空間,而(2)中data段數據只有4個字節,但實際上(2)也占用了16字節的空間,其中不足的部分都用0補全了。所以推測,若段中數據為N個字節,則該段實際占用的空間為 ([N/16]+1)*16 個字節([]為取整符號)。
實驗任務三
將下面的程序編譯、鏈接,用debug加載、跟蹤,然后回答問題。
1 assume cs:code, ds:data, ss:stack 2 3 code segment 4 start: mov ax,stack 5 mov ss, ax 6 mov sp,16 7 8 mov ax, data 9 mov ds, ax 10 11 push ds:[0] 12 push ds:[2] 13 pop ds:[2] 14 pop ds:[0] 15 16 mov ax,4c00h 17 int 21h 18 19 code ends 20 data segment 21 dw 0123h, 0456h 22 data ends 23 24 stack segment 25 dw 0,0 26 stack ends 27 end start
①CPU執行程序,程序返回前,data段中的數據是多少?
②CPU執行程序,程序返回前,CS=____,SS=____,DS=____。
③設程序加載后,code段的段地址為X,則data段的段地址為____,stack段的段地址為____。
實現:
將代碼編譯、連接后,用debug工具調試:
①可以發現,data段的數據在執行程序后,程序返回前並未改變,仍是原始數據。
②從圖中可以看出,CPU執行程序,程序返回前,CS=076A,SS=076E,DS=076D。
③進一步可以發現,若code段的段地址為X,則data段的段地址為X+3,stack段的段地址為X+4。
總結:對比(2)(3),發現它們僅僅是data段、stack段和code段的順序交換了一下,其內容都一樣,但是段地址間的相互關系卻發生了變化。 進一步觀察發現,各段段地址的大小關系與各段在代碼中出現的先后關系是一致的,而相鄰兩段段地址的差值是由前段段占用內存空間大小決定的。實際上,各段在程序中出現的先后順序是決定了各自被加載進內存的順序。
實驗任務四
如果將(1)(2)(3)題中的最后一條偽指令“end start”改為“end”(也就是說,不指明程序的入口),則哪個程序仍然可以正確執行?請說明原因。
答:如果將最后一條偽指令“end start”改為“end”,相當於沒有指明程序入口,此時程序就會從加載進內存的第一個單元起開始執行。在(1)(2)題中,都是數據先加載進內存,CPU會誤把數據也當成指令執行,最終不能保證被正確執行;而(3)題則是代碼段先被加載進內存,因而可以被正確執行。
實驗任務五
程序如下,編寫code段中的代碼,將a段和b段中的數據依次相加,將結果存到c段中。
1 assume cs:code 2 a segment 3 db 1,2,3,4,5,6,7,8 4 a ends 5 6 b segment 7 db 1,2,3,4,5,6,7,8 8 b ends 9 10 c segment ; 在集成軟件環境中,請將此處的段名稱由c→改為c1或其它名稱 11 db 8 dup(0) 12 c ends ; 改的時候要成對一起修改 13 code segment 14 start: 15 ;? 16 code ends 17 end start
實現:
此題需要存放數據的段有3個,即a、b、c,但是任意時刻,只有一個 ds 和 es 可用。通過前面的實驗可以得知,a段的段地址和b段的段地址 是有聯系的,此例中,由於a、b段的數據都小於16個字節,設a段的段地址為X,則b段的段地址為X+1。據此可以得到一種實現方案:
補充的代碼為:
mov ax,c mov ds,ax ;將ds作為c段的段地址 mov ax,a mov es,ax ;將es作為a段的段地址 mov bx,0 mov cx,8 s: mov dl,es:[bx] add [bx],dl mov dl,es:[bx+16] ;b:[bx]對應於 a:[bx+16] add [bx],dl inc bx loop s mov ax,4c00h int 21h
可以看到,此方案成功實現了a段與b段依次相加的目的。
除此之外,還可以有另一種方案,即分階段使用ds:
補充的代碼為:
mov ax,a mov ds,ax ;ds作為邏輯段a mov ax,c mov es,ax ;es作為邏輯段c
;階段一:將邏輯段a的數據復制到邏輯段c中 mov bx,0 mov cx,8 s1: mov al,[bx] mov es:[bx],al inc bx loop s1 mov ax,b mov ds,ax ;ds作為邏輯段b
;階段二:將b段的數據依次加到c上 mov bx,0 mov cx,8 s2: mov al,[bx] add es:[bx],al inc bx loop s2 mov ax,4c00h int 21h
可以看到,此方案實現了a段復制到c段和b段加到c段上兩個階段的任務,最終也實現了將a、b段數據依次相加的目的。
實驗任務六
程序如下,編寫code段中的代碼,用push指令將a段中的前8個字符型數據,逆序存儲到b段中。
1 assume cs:code 2 a segment 3 dw 1,2,3,4,5,6,7,8,9,0ah,0bh,0ch,0dh,0eh,0fh,0ffh 4 a ends 5 6 b segment 7 dw 8 dup(0) 8 b ends 9 10 code segment 11 start: 12 ;? 13 code ends 14 end start
實現:
補充的代碼為:
mov ax,a mov ds,ax mov ax,b mov ss,ax ;將b段設置為棧 mov sp,16 ;棧頂為16 mov bx,0 mov cx,8 s: push [bx] add bx,2 loop s mov ax,4c00h int 21
在push之前,b段的內容都為0,入棧全部結束后,b段逆序存儲了a段的前8個字節。