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


實驗任務一

將下面的程序編譯、鏈接,用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個字節。 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM