for迴圈和Dowhile迴圈的應用
一、實驗目的
1.理解和掌握將資料、程式碼、棧放入不同邏輯段的程式的編寫和除錯 2.理解具有多個段的彙編源程式對應的目標程式執行時,記憶體分配方式 3.掌握大小寫字元的轉換方法、數字字元和數值之間的轉換方法4.理解並掌握各種定址方式的靈活應用
5.掌握彙編指令loop, and, or,div, mul的用法
二、實驗準備
複習教材chapter 6-8章。- chapter 6包含多個段的程式
- chapter 7更靈活的定位記憶體地址的方法
- chapter 8資料處理的兩個基本問題
三、實驗內容
1.實驗任務1
使用任意文字編譯器,錄入彙編源程式task1.asm。
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: 9 mov ax, data 10 mov ds, ax 11 12 mov ax, 0b800H 13 mov es, ax 14 15 mov cx, 5 16 mov si, 0 17 mov di, 0f00h 18 s: moval, [si] 19 and al, 0dfh 20 mov es:[di], al 21 mov al, [5+si] 22 mov es:[di+1], al 23 inc si 24 add di, 2 25 loop s 26 27 mov ah, 4ch 28 int 21h 29 code ends 30 end start
閱讀源程式,從理論上分析原始碼的功能,尤其是line15-25,迴圈實現的功能是什麼,逐行理解每條指令的功能。
- 使用masm、link對task1.asm進行彙編、連結,得到可執行檔案task1.exe,執行並觀察結果。
- 使用debug工具對程式進行除錯,執行到程式返回前,即line27之前,觀察結果。
- 修改line4裡5個位元組單元的值,重新彙編、連結、執行,觀察結果。
1 db 5 dup(2) 2 --> 改成: 3 db 2,3,4,5,6基於觀察,分析、猜測這裡的數值作用是什麼。
2.實驗任務2
已知資料段data中定義位元組資料如下:
1 data segments 2 db 23,50,66,71,35 3 data ends
編寫程式,在螢幕上以十進位制整數形式列印輸出這5個兩位數。
提示:
1個兩位數如何輸出思路如下:
具體處理步驟如下:
第1步,利用除法指令div,計算出每個數位上的數值。
第2步,利用數值和數字字元之間ascII碼的關係,把數值→數字字元
第3步,利用系統功能呼叫int 21h中的2號子功能,輸出單個字元。
int 21h中的2號子功能說明如下:
功能:輸出單個字元
用法:
1 mov ah,2 2 mov d1,xx ;xx是待輸出的字元,或其ASCII碼值 3 int 21h
5個兩位數如何輸出
利用loop指令,以及,靈活的定址方式。
3.實驗任務3
教材「實驗5編寫、除錯具有多個段的程式」(1)
程式原始碼見task3.asm。
4.實驗任務4
教材「實驗5編寫、除錯具有多個段的程式」(2)
程式原始碼見task4.asm。
5.實驗任務5
教材「實驗5編寫、除錯具有多個段的程式」(3)
程式原始碼見task5.asm。
6.實驗任務6
教材「實驗5編寫、除錯具有多個段的程式」(4)
7.實驗任務7
教材「實驗5編寫、除錯具有多個段的程式」(5)
程式原始碼見task7.asm。
注*:如果在整合軟體環境下編寫、彙編這個實驗任務,請將段名為c的邏輯段,名稱改為c1或別的標識 符。由於早期一些指令集中使用c指代暫存器,如不更正,有些彙編器在彙編時會報錯。
1 c segment ;段名稱改成c1或別的合法的識別符號 2 ... 3 c ends ;c1
8.實驗任務8
教材「實驗5編寫、除錯具有多個段的程式」(6)
程式原始碼見task8.asm。
四、實驗結論
1.實驗任務1
task1:
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: 9 mov ax, data 10 mov ds, ax 11 12 mov ax, 0b800H 13 mov es, ax 14 15 mov cx, 5 16 mov si, 0 17 mov di, 0f00h 18 s: mov al, [si] 19 and al, 0dfh 20 mov es:[di], al 21 mov al, [5+si] 22 mov es:[di+1], al 23 inc si 24 add di, 2 25 loop s 26 27 mov ah, 4ch 28 int 21h 29 code ends 30 end start
使用masm,link對task1.asm進行彙編,連結,得到可執行檔案,執行並觀察結果:
使用debug工具對程式進行除錯:
修改line4裡5個位元組單元的值,重新彙編、連結、執行,觀察結果。
1 db 5 dup(2) 2 --> 改成: 3 db 2,3,4,5,6
猜想:修改之後字元顏色發生了變化,內容沒有變化。通過分析可以得到:db 5 dup(2)表示分配5個位元組記憶體空間並初始化為2,db 2,3,4,5,6 表示分配5個位元組記憶體空間並相應的賦值為2,3,4,5,6。通過上面的結果觀察可知,修改的數值對應著字元的顏色,對內容並無影響。
2.實驗任務2
1 assume cs:code,ds:data 2 data segment 3 db 23,50,66,71,35 4 data ends 5 code segment 6 start: 7 mov ax,data 8 mov ds,ax 9 mov di,0 10 mov cx,5 11 12 s1: mov ah,0 13 mov al,ds:[di] 14 mov bl,10 15 div bl 16 mov ds:[10+di],al 17 mov ds:[11+di],ah 18 19 mov ah,2 20 mov dl,ds:[10+di] 21 add dl,30h 22 int 21h 23 24 mov ah,2 25 mov dl,ds:[11+di] 26 add dl,30h 27 int 21h 28 29 mov ah,2 30 mov dl," " 31 int 21h 32 33 inc di 34 loop s1 35 36 mov ax,4c00h 37 int 21h 38 code ends 39 end start
3.實驗任務3
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
(1)執行之後,發現數據段的內容並沒有改變:
(2)在程式返回前,cs=076C,ss=076B,ds=076A (3)設程式載入後,code段的段地址為X,則data段的段地址為X-2,stack段的段地址為X-1。4.實驗任務4
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
(1)data段資料並未發生變化:0123h,0456h
(2)在程式返回前,cs=076C,ss=076B,ds=076A
(3)設程式載入後,code段的段地址為X,則data段的段地址為X-2,stack段的段地址為X-1
(4)對於如下定義的段:
1 name segment 2 ... 3 name ends
如果段中的資料佔N個位元組,則程式載入後,該段實際佔有的空間為 16×(N/16) 位元組。
5.實驗任務5
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
(1)CPU執行程式,程式返回前,data段中的資料為 0123H,0456H
(2)CPU執行程式,程式返回前,cs=076AH,ss=076EH,ds=076DH。
(3)設程式載入後,code段的段地址為X,則data段的段地址為X+3,stack段的段地址為X+4。
6.實驗任務6
如果將(1)、(2)、(3)題中的最後一條偽指令“end start”改為“end”(也就是說,不指明程式的入口),則哪個程式仍然可以執行?請說明原因。
答:只有任務5的彙編程式可以正常執行。因為任務5程式的程式碼段定義於資料段和棧段之前,在順序執行的過程中會首先執行code segment,而不會因執行了data segment和stack segment導致程式出現不符合預期的情況。
7.實驗任務7
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 c1 segment ; 在整合軟體環境中,請將此處的段名稱由c→改為c1或其它名稱 11 db 8 dup(0) 12 c1 ends 13 14 code segment 15 start: 16 mov ax,a 17 mov ds,ax 18 mov cx,8 19 mov si,0 20 21 s: mov ax,[si] 22 add ax,[si+10H] 23 mov [si+20H],ax 24 inc si 25 loop s 26 mov ax,4c00h 27 int 21h 28 code ends 29 end start
8.實驗任務8
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 mov ax,a 13 mov ds,ax 14 15 mov ax,b 16 mov ss,ax 17 mov sp,16 18 mov si,0 19 20 mov cx,8 21 22 s: push ds:[si] 23 add si,2 24 loop s 25 mov ax,4c00h 26 int 21h 27 code ends 28 end start