實驗4 8086標志寄存器及中斷


1. 實驗任務1
  驗證性實驗:有些匯編指令會影響到標志寄存器中的一個或多個狀態標志位。
  在debug環境中,分別實踐、觀察:
  ① add指令對標志寄存器中的零標志位ZF(Zero Flag)、進位標志位CF(Carry Flag)是否有影響?
  ② inc指令對標志寄存器中的零標志位ZF(Zero Flag)、進位標志位CF(Carry Flag)是否有影響?

  可以看到add對零標志位有影響,因為溢出一位后剩余位為0。對進位標志位也有影響,因為產生了進位。

  inc對零標志位有影響,因為溢出一位后剩余位為0。對進位標志位沒有影響,可見inc產生的進位不會被記錄下來。

   
  使用任意文本編輯器,錄入8086匯編源碼task1.asm。
  task1.asm
 1 assume cs:code, ds:data
 2 
 3 data segment
 4    x dw 1020h, 2240h, 9522h, 5060h, 3359h, 6652h, 2530h, 7031h
 5    y dw 3210h, 5510h, 6066h, 5121h, 8801h, 6210h, 7119h, 3912h
 6 data ends
 7 code segment 
 8 start:
 9     mov ax, data
10     mov ds, ax
11     mov si, offset x
12     mov di, offset y
13     call add128
14 
15     mov ah, 4ch
16     int 21h
17 
18 add128:
19     push ax
20     push cx
21     push si
22     push di
23 
24     sub ax, ax
25 
26     mov cx, 8
27 s:  mov ax, [si]
28     adc ax, [di]
29     mov [si], ax
30 
31     inc si
32     inc si
33     inc di
34     inc di
35     loop s
36 
37     pop di
38     pop si
39     pop cx
40     pop ax
41     ret
42 code ends
43 end start
  其中:
  add128是子程序子程序。
  功能:實現計算兩位128位數的加法
  入口參數:
  ds:si指向存儲第一個128位數的存儲空間(因為一個數128位,需要8個字節的連續空間)
  ds:di指向存儲第二個128位數的存儲空間
  出口參數:
  加運算后的結果,保存在第一個數的存儲空間中,即:ds:si開始的連續8個字節空間
  在代碼段種,調用add128實現對標號x和y處存儲的兩個128位數據相加,結果保存在x處的連續128個字節中。
  對程序進行匯編、鏈接,得到可執行程序task1.exe。在debug中調試程序,並回答問題。
 

 

  ① line31~line34的4條inc指令,能否替換成如下代碼?你的結論的依據/理由是什么?
1 add si, 2
2 add di, 2
  若替換成如上代碼,仍然可以得到正確答案。因為si與di的范圍都在0~16內,對其進行自增運算並不會產生進位,而且樣例中每個字的加法均沒有產生進位,因此不會影響結果。
  但是邏輯上並不能夠將上述代碼替換,如果某個字的相加產生了進位,那么計算結果將產生錯誤。

 

  ② 在debug中調試,觀察數據段中做128位加之前,和,加之后,數據段的值的變化。
2. 實驗任務2
  使用任意文本編輯器,錄入8086匯編源碼task2.asm。
  task2.asm 
 1 assume cs:code, ds:data
 2 data segment
 3         str db 80 dup(?)
 4 data ends
 5 
 6 code segment
 7 start:  
 8         mov ax, data
 9         mov ds, ax
10         mov si, 0
11 s1:        
12         mov ah, 1
13         int 21h
14         mov [si], al
15         cmp al, '#'
16         je next
17         inc si
18         jmp s1
19 next:
20         mov ah, 2
21         mov dl, 0ah
22         int 21h
23         
24         mov cx, si
25         mov si, 0
26 s2:     mov ah, 2
27         mov dl, [si]
28         int 21h
29         inc si
30         loop s2
31 
32         mov ah, 4ch
33         int 21h
34 code ends
35 end start
  對源程序task2.asm進行匯編、鏈接,得到可執行文件task2.exe。
  運行程序,從鍵盤上輸入一串字符,以#結束(比如,輸入George Orwell, 1984#),觀察結果。結合運行結果,理解代碼並回答問題:
  ① 匯編指令代碼line11-18,實現的功能是?
  ② 匯編指令代碼line20-22,實現的功能是?
  ③ 匯編指令代碼line24-30,實現的功能是?
 
 ①匯編指令代碼line11-18,實現的功能是從鍵盤輸入一個字符並存入數據段偏移地址為si的位置。每輸入一個字符si進行自增運算,並無條件跳轉到標記s1處,若字符為"#",則標志寄存器CF值為ZR,此時條件指令je指令執行跳轉到標記next處。
 
② 匯編指令代碼line20-22,實現的功能是輸出換行符,換行符的十六進制ASCII碼值就是0AH。
 
③ 匯編指令代碼line24-30,實現的功能是將數據段中長度為si的字符串輸出。

 

  說明:task2.asm中用到的兩個DOS系統功能調用:
    DOS系統功能調用int 21h的1號子功能
    功能:從鍵盤上輸入單個字符
    入口參數:(ah) = 1
    出口參數: (al)存放輸入字符的ASCⅡ碼
    即:
1 mov ah, 1 
2 int 21h     ; (al) <-- 輸入字符的ascⅡ碼
    DOS系統功能調用int 21h的2號子功能
    功能:輸出單個字符到屏幕上
    入口參數:(ah) = 2, (dl) = 待輸出的字符或其ascⅡ碼
    出口參數:無
    即:
1 mov ah, 2 
2 mov dl, ×× ; ××是待輸出的字符,或,其ascⅡ碼 
3 int 21h

 

3. 實驗任務3
  針對8086CPU,已知邏輯段定義如下:
1 data segment 
2     x dw 91, 792, 8536, 65521, 2021 
3     len equ $ - x 
4 data ends
  編寫8086匯編源程序task3.asm,在屏幕上以十進制形式輸出data段中這一組連續的數據,數據和數據之間以空格間隔。
  要求:
    編寫子程序printNumber
    功能:以十進制形式輸出一個任意位數的整數(整數范圍0 ~ 65535)
    入口參數:寄存器ax(待輸出的數據 --> ax)
    出口參數:無
  編寫子程序printSpace
    功能:打印一個空格
    入口參數:無
    出口參數:無
  在主體代碼中,綜合應用尋址方式和循環,調用printNumber和printSpace, 實現題目要求。
 1 assume cs:code, ds:data
 2 data segment
 3         x dw 91, 792, 8536, 65521, 2021 
 4         len equ $ - x
 5 data ends
 6 
 7 stack segment
 8         db 16 dup(0)
 9 stack ends
10 
11 code segment
12 start:  
13         mov ax, data
14         mov ds, ax
15 
16         mov cx, 5
17         mov si, offset x
18 s:      mov ax, ds:[si]
19         call printNumber
20         call printSpace
21         inc si
22         inc si
23         loop s
24 
25         mov ah, 4ch
26         int 21h
27 
28 printNumber:
29         mov bx, 0AH     ;除數
30         mov dx, 0       ;高位置為0,記錄余數
31         mov di, 0
32         push cx
33  s1:    div bx
34         push dx         ;余數入棧
35         inc di
36         mov dx, 0
37         cmp ax, 0       ;被除數為0時結束
38         je next
39         jmp s1
40 next:   mov ah, 2
41         mov cx, di
42 s2:     pop dx
43         or dl, 30H      ;數字轉字符
44         int 21h
45         loop s2
46 
47         pop cx
48         ret
49 
50 printSpace:
51         mov dl, ' '
52         mov ah, 2
53         int 21h
54         ret
55 code ends
56 end start
 

 

4. 實驗任務4
  針對8086CPU,已知邏輯段定義如下:
1 data segment 
2     str db "assembly language, it's not difficult but tedious" 
3     len equ $ - str 
4 data ends
  編寫8086匯編源程序task4.asm,將data段中字符串里的小寫字符轉換成大寫。
  要求:
  編寫子程序strupr
    功能:將包含任意字符的字符串中的小寫字母變成大寫
    入口參數
      (ds:si ) 字符串首地址的段地址和偏移地址分別送至ds和si
      (cx) 字符串的長度
    出口參數:無
  在主體代碼中,設置入口參數,調用strupr, 實現題目要求。
 
 1 assume cs:code, ds:data
 2 data segment 
 3         str db "assembly language, it's not difficult but tedious" 
 4         len equ $ - str 
 5 data ends
 6 
 7 stack segment
 8         db 16 dup(0)
 9 stack ends
10 
11 code segment
12 start:  
13         mov ax, data
14         mov ds, ax
15 
16         mov cx, len
17         mov si, offset str
18         call strupr
19 
20         mov ah, 4ch
21         int 21h
22 strupr:
23 s:      mov al, byte ptr ds:[si]
24         cmp al, 'a'
25         jb next
26         cmp al, 'z'
27         ja next
28 
29         mov ah, 2               ;若是小寫字母
30         and al, 11011111b       ;轉大寫
31         mov dl, al
32         int 21h                 ;輸出
33         inc si
34         loop s
35 
36         cmp cx, 0
37         je return
38 
39 next:   mov ah, 2               ;若是其他字符,直接輸出
40         mov dl, al
41         int 21h
42         inc si
43         loop s
44 return:
45         ret
46 code ends
47 end start

 

5. 實驗任務5
  使用任意文本編輯器,錄入8086匯編源碼task5.asm。
  task5.asm
 
 1 assume cs:code, ds:data
 2 
 3 data segment
 4     str1 db "yes", '$'
 5     str2 db "no", '$'
 6 data ends
 7 
 8 code segment
 9 start:
10     mov ax, data
11     mov ds, ax
12 
13     mov ah, 1
14     int 21h
15 
16     mov ah, 2
17     mov bh, 0
18     mov dh, 24
19     mov dl, 70
20     int 10h
21 
22     cmp al, '7'
23     je s1
24     mov ah, 9
25     mov dx, offset str2
26     int 21h
27 
28     jmp over
29 
30 s1: mov ah, 9
31     mov dx, offset str1
32     int 21h
33 over:  
34     mov ah, 4ch
35     int 21h
36 code ends
37 end start
  對源程序task5.asm進行匯編、鏈接,得到可執行文件task5.exe。
  運行程序,輸入7,觀察結果。輸入其他字符,觀察結果。結合運行結果和注釋,理解代碼實現的功能。
 
  說明:task5.asm中,使用用到的DOS系統功能調用和BIOS中斷例程
    DOS系統功能調用int 21h的1號子功能
    功能:從鍵盤上輸入單個字符
    入口參數:(ah) = 1
    出口參數: (al)存放輸入字符的ASCⅡ碼
    即:
1 mov ah, 1 
2 int 21h     ; (al) <-- 輸入字符的ascⅡ碼
    DOS系統功能調用int 21h的9號子功能
    功能:顯示字符串
    入口參數:(ah) = 9,(ds:dx) = 字符串的首地址的段地址和偏移地址
    出口參數: 無
    其它要求:字符串必須以$結束
    即:
1 mov ah, 9 
2 mov ds, ××     ; ××是待輸出字符串所在段的段地址 
3 mov dx, ××     ; ××是待輸出字符串第一個字符的偏移地址 
4 int 21h
    BIOS中斷例程int 10h的2號子功能
    功能:設置光標位置
    入口參數:(ah) = 2, (bh) = 頁號(默認取0), (dh) = 行號, (dl) = 列號
    出口參數:無
    即:
1 mov ah, 2 
2 mov bh, ××     ; ××是頁號 
3 mov dh, ×× 
4 mov dl, ××      ; ××是列號 
5 int 10h

 

   task5重點在於匯編語言分支結構的運用。使用cmp指令以及對零標志寄存器進行判斷以及指令跳轉。上述結果表示如果輸入的字符不為7,則在屏幕指定位置輸出no,若為7,則在相同位置輸出yes。

 

6. 實驗任務6
  實驗任務1、2、3、5中使用了不少系統提供的中斷例程。本實驗任務中,要求自行實現一個42號軟中斷例程,使得通過 int 42 或 int 2ah 軟中斷調用,實現在屏幕最下方中間以黑底綠字打印"welcome to 2049!"。
  建議配合教材第12章學習理解並實踐。
  task6_1.asm
 1 assume cs:code
 2 
 3 code segment
 4 start:
 5     ; 42 interrupt routine install code
 6     mov ax, cs
 7     mov ds, ax
 8     mov si, offset int42  ; set ds:si
 9 
10     mov ax, 0
11     mov es, ax
12     mov di, 200h        ; set es:di
13 
14     mov cx, offset int42_end - offset int42
15     cld
16     rep movsb
17 
18     ; set IVT(Interrupt Vector Table)
19     mov ax, 0
20     mov es, ax
21     mov word ptr es:[42*4], 200h
22     mov word ptr es:[42*4+2], 0
23 
24     mov ah, 4ch
25     int 21h
26 
27 int42: 
28     jmp short int42_start
29     str db "welcome to 2049!"
30     len equ $ - str
31 
32     ; display string "welcome to 2049!"
33 int42_start:
34     mov ax, cs
35     mov ds, ax
36     mov si, 202h
37 
38     mov ax, 0b800h
39     mov es, ax
40     mov di, 24*160 + 32*2
41 
42     mov cx, len
43 s:  mov al, [si]
44     mov es:[di], al
45     mov byte ptr es:[di+1], 2
46     inc si
47     add di, 2
48     loop s
49 
50     iret
51 int42_end:
52    nop
53 code ends
54 end start
  task6_2.asm 
 1 assume cs:code
 2 
 3 code segment
 4 start:
 5     int 42
 6 
 7     mov ah, 4ch
 8     int 21h
 9 code ends
10 end start
  對匯編源程序task6_1.asm進行匯編、鏈接,得到可執行程序task6_1.exe。運行task6_1.exe,實現將42號中斷處理程序安裝到0:200開始的連續內存空間,並設置中斷向量表,使得將來通過 int 42 ,系統可以跳轉到中斷處理程序。
  對匯編源程序task6_2.asm進行匯編、鏈接,得到可執行程序task6_2.exe。運行task6_2.exe。 

   軟中斷是通過執行中斷指令產生的,是軟件層面對進程的中斷,匯編語言的軟中斷可以理解為高級語言中函數的調用。上述例子中對中斷號的自定義可以靈活地執行編程需要的操作。


免責聲明!

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



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