組合語言程式設計第三次實驗 多個段的彙編源程式編寫與除錯
一、實驗目的
1. 理解和掌握將資料、程式碼、棧放入不同邏輯段的程式的編寫和除錯
2. 理解具有多個段的彙編源程式對應的目標程式執行時,記憶體分配方式
3. 掌握大小寫字元的轉換方法、數字字元和數值之間的轉換方法
4. 理解並掌握各種定址方式的靈活應用
5. 掌握彙編指令loop, and, or,div, mul的用法
二、實驗準備
複習教材chapter 6-8章。
chapter 6 包含多個段的程式
chapter 7 更靈活的定位記憶體地址的方法
chapter 8 資料處理的兩個基本問題
三、實驗內容
1. 實驗任務1
(1)原始碼檔案task.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: 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
(2)從理論上分析原始碼的功能。
mov cx, 5 //將cx暫存器賦值為5,設定迴圈次數 mov si, 0 //設定資料段偏移地址為0mov di, 0f00h //設定es段的偏移地址為0f00h s: mov al, [si] //將記憶體單元ds:[si]中的資料傳入al and al, 0dfh //將al中的字母變成大寫 mov es:[di], al //將al中的資料賦值給es:[di] mov al, [5+si] //將ds:[5*si]中的資料傳給al mov es:[di+1], al //將al中的資料傳給es:[di+1] inc si //將ds的偏移地址si加1 add di, 2 //將es的偏移地址di加2
loop s //轉移到s:的開始位置,cx-1,在cx大於0的情況下繼續迴圈
(3)使用masm、link對task1.asm進行彙編、連結,得到可執行檔案task.exe,執行並觀察結果。
(4)使用debug工具對程式進行除錯,執行到程式返回前,觀察結果。
(5)修改line裡5個位元組單元的值,重新彙編、連線、執行,觀察結果。
1 assume cs:code, ds:data 2 data segment 3 db 'Nuist' 4 db 2,3,4,5,6 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
觀察到數值的顏色發生了變化,猜測這裡5個位元組單元的值的作用是設定字型的顏色。
2.實驗任務2
(1)已知資料段data中定義位元組資料如下:
1 data segments 2 db 23, 50, 66, 71, 35 3 data ends
編寫程式,在螢幕上以十進位制整數形式列印輸出這5個兩位數。
提示: 1個兩位數如何輸出
思路如下:
具體處理步驟如下:
第1步,利用除法指令div,計算出每個數位上的數值。
第2步,利用數值和數字字元之間ascⅡ碼的關係,把數值→數字字元。
第3步,利用系統功能呼叫int 21h中的2號子功能,輸出單個字元。
int 21h中的2號子功能說明如下:
功能:輸出單個字元
用法:
1 mov ah, 2 2 mov dl, ×× ; ××是待輸出的字元,或其ASCⅡ碼值 3 int 21h
5個兩位數如何輸出?:利用loop指令,以及,靈活的定址方式。
(2)原始碼檔案task2.asm
1 assume cs:code, ds:data, ss:stack 2 data segment 3 db 23, 50, 66, 71, 35 4 data ends 5 6 stack segment 7 db 2 dup(0) 8 stack ends 9 10 code segment 11 start: 12 mov ax, data 13 mov ds, ax 14 15 mov ax, stack 16 mov ss, ax 17 mov sp, 10h 18 19 mov cx, 5 20 mov si, 0 21 s: mov ah, 0 ;ah存放餘數,al存放商 22 mov al, ds:[si] 23 mov bl, 10 24 div bl 25 push ax ;8086彙編進行push、pop只對字操作 26 27 pop bx 28 mov ah, 2 29 mov dl, bl 30 add dl, 30h 31 int 21h 32 33 mov ah, 2 34 mov dl, bh 35 add dl, 30h 36 int 21h 37 38 mov ah, 2 39 mov dl, " " 40 int 21h 41 42 inc si 43 loop s 44 45 mov ah, 4ch 46 int 21h 47 code ends 48 end start
(3)使用masm、link對task1.asm進行彙編、連結,得到可執行檔案task.exe,執行並觀察結果。
3.實驗任務3
(1)原始碼檔案task3.asm
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
(2)教材上的①②③三個問題
①data段中的資料是:23 01 56 04 89 07 bc 0a ef 0d ed 0f ba 0c 87 09
觀察到的結果和理論分析一致。
②cs=0766,ss=0765,ds=0764
③程式載入後,code段的段地址為X,則data段的段地址為X-2,stack段的段地址為X-1。
4.實驗任務4
(1)原始碼task4.asm
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
(2)回答教材中①②③④四個問題
①CPU執行程式,程式返回前,data段中的資料是23 01 56 04。
②CPU執行程式,程式返回前,cs=0766,ss=0765,ds=0764。
③程式載入後,code段的段地址為X,則data段的段地址為X-2,stack段的段地址為X-1。
④對於如下定義的段:
name segment
……
name ends
如果段中的資料佔N個位元組,則程式載入後,該段實際佔有的空間為int(N/16+1)*16。
5.實驗任務5
(1)原始碼檔案task5.asm
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
(2)回答教材中①②③三個問題
①CPU執行程式,程式返回前,data段中的資料為 23 01 56 04.
②CPU執行程式,程式返回前,cs=076A,ss=076E,ds=076D。
③程式載入後,code段的段地址為X,則data段的段地址為X+4,stack段的段地址為X+3。
6.實驗任務6
(1)回答教材中提出的問題,並按要求說明原因。
問:如果將task3.asm、task4.asm、task5.asm中的最後一條偽指令“end start”改為“end”(也就是說不指明程式的入口),則哪個程式仍然可以正常執行?請說明原因。
答:task5.asm在彙編、連結之後可以執行。因為程式段在最前面,在不指明的情況下,預設程式段從頭開始。
7.實驗任務7
(1)原始碼檔案task7.asm
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 11 db 8 dup(0) 12 c1 ends 13 14 code segment 15 start: 16 mov ax,a 17 mov ds,ax 18 19 mov ax,c1 20 mov es,ax 21 22 mov si,0 23 mov cx,8 24 mov ax,0 25 26 s: mov ax,ds:[si] 27 add ax,ds:[si+10h] 28 mov es:[si],ax 29 30 inc si 31 mov ax,0 32 loop s 33 34 mov ax,4ch 35 int 21h 36 code ends 37 end start
(2)附上在debug環境中,執行到程式返回前,檢視邏輯段c的資料的截圖,以此驗證所編寫的程式正 確實現了題目要求。
8.實驗任務8
(1)原始碼檔案task8.asm
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 cx, 8 16 mov si, 0 17 s: push ds:[si] 18 add si, 2 19 loop s 20 21 mov ax, b 22 mov ds, ax 23 24 mov cx, 8 25 mov si, 0 26 s1: pop ds:[si] 27 add si, 2 28 loop s1 29 30 mov ax, 4ch 31 int 21h 32 code ends 33 end start
(2)附上在debug環境中,執行到程式返回前,檢視邏輯段c的資料的截圖,以此驗證所編寫的程式正 確實現了題目要求。
五、實驗總結
1、將資料段和棧段放在程式碼段後邊的時候,計算精確反彙編的時候出現了問題,使用d命令檢視後得知,如果不是最後一個段,那麼它所佔的位元組數一定是16的倍數,因此程式碼段後邊會有一部分空間儲存的不是程式碼資料。