1. 程式人生 > 其它 >實驗4 8086標誌暫存器及中斷

實驗4 8086標誌暫存器及中斷

實驗任務1

task4_1.asm原始碼:

assume cs:code, ds:data

data segment
   x dw 1020h, 2240h, 9522h, 5060h, 3359h, 6652h, 2530h, 7031h
   y dw 3210h, 5510h, 6066h, 5121h, 8801h, 6210h, 7119h, 3912h
data ends
code segment
start:
    mov ax, data
    mov ds, ax
    mov si, offset x
    mov di, offset y
    call add128

    mov ah, 4ch
    
int 21h add128: push ax push cx push si push di sub ax, ax mov cx, 8 s: mov ax, [si] adc ax, [di] mov [si], ax inc si inc si inc di inc di loop s pop di pop si pop cx pop ax ret code ends end start

回答問題:

  line31~line34的4條inc指令,能否替換成如下程式碼?你的結論的依據/理由是什麼?

答:不能。原因:因為如果使用add會導致進位暫存器CF的值發生變化。如果本來應當是有進位的,CF的值為CY(1),但是做了add操作後CF會變成NC(0),會對後面的位數加法產生影響。所以不能使用add

除錯截圖:

實驗任務2:

task4_2.asm原始碼:

assume cs:code, ds:data
data segment
        str db 80 dup(?)
data ends

code segment
start:
        mov ax, data
        mov ds, ax
        mov si, 0
s1:
        mov ah, 
1 int 21h mov [si], al cmp al, '#' je next inc si jmp s1 next: mov ah, 2 mov dl, 0ah int 21h mov cx, si mov si, 0 s2: mov ah, 2 mov dl, [si] int 21h inc si loop s2 mov ah, 4ch int 21h code ends end start

① 彙編指令程式碼line11-18,實現的功能是?

答:從鍵盤上讀取輸入的字元,並儲存到ds:[si],每讀入一個就判斷是否為#,如果是則不儲存,轉跳至標號next處執行;如果不是則si + 1並繼續讀入下一個字元。

② 彙編指令程式碼line20-22,實現的功能是?

答:列印一個回車(換行符)。

③ 彙編指令程式碼line24-30,實現的功能是?

答:列印字串,並且不會把#打出來。

執行截圖:

實驗任務3:

task4_3.asm原始碼:

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

data segment
    x dw 91, 792, 8536, 65535, 2021, 0
    len equ $ - x
data ends

stack segment
    dw 8 dup(?)
stack ends

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

    mov ax, stack
    mov ss, ax
    mov sp, 16

    mov cx, len/2
    print:
        mov ax, word ptr ds:[di]
        add di, 2

        push cx
        call printNumber
        call printSpace

        pop cx
    loop print

    mov ah, 4ch
    int 21h

; 子程式: printNumber
; 功能: 列印數字
;   入口引數:
;       暫存器ax  (待輸出的資料 --> ax)
;   區域性變數說明:
;       bx -> 儲存數字字元個數
printNumber:
    mov bx, 0
    ; getEach迴圈: 獲取每一位,然後壓入棧中
    getEach:
        ; 除數放在16位暫存器bp中
        mov bp, 10
        mov dx, 0
        div bp

        push dx
        inc bx

        mov cx, ax
        inc cx

    loop getEach

    ; 列印數字
    mov cx, bx
    printEach:
        pop dx
        add dl, 30h
        mov ah, 2
        int 21h
    loop printEach

    ret

; 子程式: printSpace
; 功能: 列印空格
printSpace:
    mov ah, 2
    mov dl, 20h
    int 21h
    ret

code ends
end start

執行截圖:

實驗任務4:

task4_4.asm原始碼:

assume ds:data,cs:code
data segment
    str db "assembly language, it's not difficult but tedious"
    len equ $ - str
data ends
code segment
start:
    mov ax, data
    mov ds, ax
    mov si, 0       ;資料段指標
    mov cx, len     ;字串長度
    call strupr     ;呼叫小寫轉大寫子程式
    jmp exit        ;退出程式

strupr:             
s:
    mov al, [si]    ;當前字元放入al
    cmp al, 61h     ;ASCII碼在[61h,7ah]為小寫字母
    jb s1
    cmp al, 7ah
    ja s1
    and al, 0dfh    ;二進位制位第三位變為0,小寫轉大寫
    mov [si], al
s1:
    inc si          ;下個字元
    loop s
    ret

exit:
    mov ah, 4ch
    int 21h
code ends
end start

子程式呼叫前:

子程式呼叫後:

可以看到字串中的小寫字母成功轉成大寫字母。

task4_5.asm原始碼:

assume cs:code, ds:data

data segment
    str1 db "yes", '$'
    str2 db "no", '$'
data ends

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

    mov ah, 1
    int 21h

    mov ah, 2
    mov bh, 0
    mov dh, 24
    mov dl, 70
    int 10h

    cmp al, '7'
    je s1
    mov ah, 9
    mov dx, offset str2
    int 21h

    jmp over

s1: mov ah, 9
    mov dx, offset str1
    int 21h
over:
    mov ah, 4ch
    int 21h
code ends
end start

輸入7:

輸入其他字元:

功能:從鍵盤鍵入一個字元,如果是7,在游標位置(24行70列)列印str1;是其他字元,在游標位置列印str2。

分析:

line13-14 鍵盤鍵入一個字元,存入al

line16-20 設定游標位置,24行70列

line22-26 al中字元不為7,在游標位置列印str2

line30-32 al中字元為7,在游標位置列印str1

實驗任務6:

task4_61.asm原始碼:

;功能:裝入42號程式中斷處理程式
assume cs:code

code segment
start:
    ; 42 interrupt routine install code
    mov ax, cs
    mov ds, ax
    mov si, offset int42  ; set ds:si

    mov ax, 0
    mov es, ax
    mov di, 200h        ; set es:di

    mov cx, offset int42_end - offset int42
    cld
    rep movsb

    ; set IVT(Interrupt Vector Table)
    mov ax, 0
    mov es, ax
    mov word ptr es:[42*4], 200h
    mov word ptr es:[42*4+2], 0

    mov ah, 4ch
    int 21h

int42: 
    jmp short int42_start
    str db "welcome to 2049!"
    len equ $ - str

    ; display string "welcome to 2049!"
int42_start:
    mov ax, cs
    mov ds, ax
    mov si, 202h

    mov ax, 0b800h
    mov es, ax
    mov di, 24*160 + 32*2

    mov cx, len
s:  mov al, [si]
    mov es:[di], al
    mov byte ptr es:[di+1], 2
    inc si
    add di, 2
    loop s

    iret
int42_end:
   nop
code ends
end start

task4_62.asm原始碼:

assume cs:code

code segment
start:
    int 42

    mov ah, 4ch
    int 21h
code ends
end start

除錯執行:

對中斷、軟中斷的理解

中斷: 中斷是指由於接收到外圍硬體(相對於CPU與記憶體而言)的非同步訊號或者來自軟體的同步訊號而進行相應的硬體/軟體處理 ;

軟中斷: 由軟體本身發給作業系統核心的中斷訊號,稱之為軟中斷 ;

中斷處理:

(1)(從中斷資訊中)取得中斷型別碼;

(2)標誌暫存器的值入棧(在中斷過程中要改變標誌暫存器的值);

(3)設定標誌暫存器的第8位TF和第9位IF的值為0;

(4)CS、IP的內容依次入棧;

(5)從記憶體地址為中斷型別碼*4和中斷型別碼*4+的兩個字單元中讀取中斷處理程式的入口地址設定IP和CS。

自定義中斷程式:41號中斷碼

中斷例程功能:

使用的中斷碼為41號,中斷例程功能為在螢幕中間顯示“201983290219 wanglicong”。

task4_63.asm原始碼:

;裝入中斷處理程式
assume cs:code
code segment
start:
    ;ds:si指向中斷處理程式
    mov ax, cs
    mov ds, ax
    mov si, offset int41

    ;es:di指向程式裝入地址
    mov ax, 0
    mov es, ax
    mov di, 200h

    ;獲取程式長度
    mov cx, offset int41end-int41
    cld
    rep movsb

    ;設定中斷向量表
    mov ax, 0
    mov es, ax
    mov word ptr es:[41*4], 200h
    mov word ptr es:[41*4+2], 0
    
    mov ah, 4ch
    int 21h

;41號中斷處理程式
int41:
    jmp short int41start
    db "201983290219 wanglicong"        ;存放要列印的字串
int41start:
    ;ds:si指向待列印字串
    mov ax, cs
    mov ds, ax
    mov si, 202h

    ;es:di指向螢幕中間
    mov ax, 0b800h
    mov es, ax
    mov di, 12*160+30*2

    ;cx字串長度
    mov cx, 13h
s:  mov al, [si]
    mov es:[di], al                 
    mov byte ptr es:[di+1], 2       ;黑底綠字
    inc si
    add di, 2
    loop s

    mov ax, 4c00h
    int 21h

int41end:nop
code ends
end start

task4_64.asm原始碼:

assume cs:code

code segment
start:
    int 41

    mov ah, 4ch
    int 21h
code ends
end start

除錯執行: