1. 程式人生 > 實用技巧 >實驗3 多個段的彙編源程式的編寫與除錯

實驗3 多個段的彙編源程式的編寫與除錯

實驗任務1:

task1.asm原始碼:

assume cs:code, ds:data
data segment
        db 'Nuist'
        db 5 dup(2)        ;db 2,3,4,5,6
data ends

code segment
start:
        mov ax, data
        mov ds, ax

        mov ax, 0b800H
        mov es, ax

        mov cx, 5
        mov si, 0
        mov di, 0f00h
s:      mov al, [si]
        
and al, 0dfh mov es:[di], al mov al, [5+si] mov es:[di+1], al inc si add di, 2 loop s mov ah, 4ch int 21h code ends end start

1、編譯、連線:

masm task1.asm; 

link task1.obj;

2、執行結果:螢幕上顯示出綠色的全為大寫的'NUIST'

3、程式碼分析:

①執行前檢視記憶體中資料段的內容:

d 076a
:0 9          ;DS+10h=076a:程式碼開始的段地址,0~9資料長度為ah

由結果可知,資料與程式碼中預存的資料完全一致;

②反彙編檢視:

1)理論上:程式碼長度(CX = 003B)= 資料段(db ‘NUIST’ :5Byte;db 5 dup(2) :5位元組)+ 程式段(3b - a = 31)

程式碼中用end start指定了程式入口,CS:IP理論上應該是:076A:000A,而實際為076B:0000,不一致;

原因:當程式段不足16位元組時,將會補足16位元組進行儲存;所以實際程式碼段長度為(3B-1)h=2bh;

檢視資料:

反彙編指令:

u 0 2a

結果:

反彙編正確;

其中,原始碼中的data被編譯器處理為一個表示段地址的值,因此也無法直接賦給段暫存器;

③執行到程式返回之前:

④程式碼理解:

 1 assume cs:code, ds:data
 2 data segment
 3         db 'Nuist'
 4         db 5 dup(2)
 5 data ends
 6 
 7 code segment
 8 start:                ;標號start
 9         mov ax, data
10         mov ds, ax
11 
12         mov ax, 0b800H      ;目標段地址設定為視訊記憶體段地址
13         mov es, ax      
14 
15         mov cx, 5         ;設定迴圈次數5
16         mov si, 0
17         mov di, 0f00h       
18 s:      mov al, [si]       ;每次迴圈將Nuist中的字元放入al
19         and al, 0dfh       ;轉換為大寫:與11011111 標綠位置0,其餘位不變
20         mov es:[di], al     ;轉換後的字元放入目標地址
21         mov al, [5+si]      ;字串迴圈的同時可以依次將取偏移地址為5~9的資料;預設dup(2)對應顯示均為綠色
22         mov es:[di+1], al    ;複製入控制顏色的位置;預設dup(2)對應顯示均為綠色
23         inc si
24         add di, 2
25         loop s
26 
27         mov ah, 4ch
28         int 21h
29 code ends
30 end start              ;用“end標號”指明源程式中指明程式的入口

⑤改變第4行程式碼:

db 2,3,4,5,6        ;db 5 dup(2)

編譯、連線,執行結果:

結果:顏色改變了;猜測:這裡的數值控制顯示的顏色。

實驗任務2:

task2.asm原始碼:

assume cs:code, ds:data
data segment
        db 23,50,66,71,35
data ends

code segment
start:
       mov ax,data
       mov ds,ax

       mov cx,5
       mov si,0
s: mov bl,10 mov ah,0       ;ah要恢復0,否則影響ax作為被除數 mov al,[si] div bl add al,30h add ah,30h mov bx,ax      ;由於輸出字元需要訪問ah,ah中的結果應先轉移 mov ah,2 mov dl,bl int 21h mov dl,bh int 21h inc si loop s mov ah,4ch int 21h code ends end start

實驗結果截圖:

成功輸出。

實驗任務3:

task3.asm源程式程式碼:

assume cs:code, ds:data, ss:stack
data segment
  dw 0123h, 0456h, 0789h, 0abch, 0defh, 0fedh, 0cbah, 0987h
data ends

stack segment
  dw 0, 0, 0, 0, 0, 0, 0, 0
stack ends

code segment
start:  mov ax,stack
        mov ss, ax
        mov sp,16
        
        mov ax, data
        mov ds, ax
        
        push ds:[0]
        push ds:[2]
        pop ds:[2]
        pop ds:[0]
        
        mov ax,4c00h
        int 21h

code ends
end start

問題:

① CPU執行程式,程式返回前,data段中資料:
23 01 56 04  ………………執行前後資料段中資料不變 
②CPU執行程式,程式返回前,(SA為程式碼段起始段地址)
cs = ss+1h    ss = ds+1h    ds = SA+10h
③設程式載入後,code段的段地址為X,則data段的段地址為:X-2h,stack段的段地址為:X-1h

1、檢視初始時各個段地址:

SA = 075A

2、反彙編:程式段長:42h-10h-10h = 22h

u 0 21

問題①執行前後資料段內容未發生改變,結論正確:

問題②:實際執行中參照量SA = 075Ah

CS = 076Ch = SS + 1h;SS = 076Bh = DS + 1h;DS = 076Ah = SA + 10h 與理論一致;

問題③:

CS = 076Ch = X;SS = 076Bh = CS - 1h;DS = 076Ah = CS - 2h 與理論一致。

實驗任務4:

task4.asm原始碼:

assume cs:code, ds:data, ss:stack
data segment
  dw 0123h, 0456h
data ends

stack segment
  dw 0, 0
stack ends

code segment
start:  mov ax,stack
        mov ss, ax
        mov sp,16
        
        mov ax, data
        mov ds, ax
        
        push ds:[0]
        push ds:[2]
        pop ds:[2]
        pop ds:[0]
        
        mov ax,4c00h
        int 21h

code ends
end start

問題:

① CPU執行程式,程式返回前,data段中資料:
23 01 56 04
②CPU執行程式,程式返回前,(SA為程式碼段起始段地址)
cs = ss+1h    ss = ds+1h    ds = SA+10h
③設程式載入後,code段的段地址為X,則data段的段地址為:X-2h,stack段的段地址為:X-1h
④如果段中資料佔N個位元組,程式載入後,該段實際佔有的空間:若N%16==0 實際N位元組;否則,實際儲存(N/16+1)*16位元組。

前三個問題:同實驗3:

由task4的執行截圖可知:

結論完全一致;

問題④:task4程式碼中data段和stack段均不足16個位元組,實際載入時,每段都補足了16位元組;

將程式碼改變如下:

assume cs:code, ds:data, ss:stack
data segment
  dw 0123h, 0456h,0123h, 0456h,0123h, 0456h,0123h, 0456h,0123h, 0456h    ;data段設定20個位元組
data ends
…………………………        ;其餘均不變

執行結果對比:

data段資料20位元組,實際儲存卻為2H(32位元組);

結論:段的儲存長度為16位元組的整數倍,不足的補全16位元組的再儲存。

實驗任務5:

task5.asm原始碼:

assume cs:code, ds:data, ss:stack

code segment
start:  mov ax,stack
        mov ss, ax
        mov sp,16
        
        mov ax, data
        mov ds, ax
        
        push ds:[0]
        push ds:[2]
        pop ds:[2]
        pop ds:[0]
        
        mov ax,4c00h
        int 21h

code ends
data segment
  dw 0123h, 0456h
data ends

stack segment
  dw 0,0
stack ends
end start

問題:

① CPU執行程式,程式返回前,data段中資料:
23 01 56 04不變
②CPU執行程式,程式返回前,(SA為程式碼段起始段地址)
cs = SA+10H    ss = ds+1H    ds =       
③設程式載入後,code段的段地址為X,則data段的段地址為:X-2h,stack段的段地址為:X-1h