實驗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