1) “int 9h 中斷例程” 和 “int 16h 中斷例程”:
1. 使用 int 9h 中斷例程對(duì)鍵盤(pán)輸入的處理
鍵盤(pán)輸入將引發(fā) 9 號(hào)中斷腹暖,BIOS 提供了 int 9 中斷例程。CPU 在 9 號(hào)中斷發(fā)生后,執(zhí)行 int 9 中斷例程睦尽,從 60h 端口讀出掃描碼,并將其轉(zhuǎn)化為相應(yīng)的 ASCII 碼或狀態(tài)信息型雳,存儲(chǔ)在內(nèi)存的指定空間(鍵盤(pán)緩沖區(qū)或狀態(tài)字節(jié))中当凡。(鍵盤(pán)緩沖區(qū)是用環(huán)形隊(duì)列結(jié)構(gòu)管理的內(nèi)存區(qū))。
一般的鍵盤(pán)輸入纠俭,在 CPU 執(zhí)行完 int 9 中斷例程后沿量,都放到了鍵盤(pán)緩沖區(qū)中。鍵盤(pán)緩沖區(qū)中有 16 個(gè)字單元冤荆,可以存儲(chǔ) 15 個(gè)按鍵的掃描碼和對(duì)應(yīng)的 ASCII 碼朴则。
2. 使用 int 16h 中斷例程讀取鍵盤(pán)緩沖區(qū)
BIOS 提供了 int 16h 中斷例程供程序員調(diào)用。int 16h 中斷例程中包含的一個(gè)最重要的功能是從鍵盤(pán)緩沖區(qū)中讀取一個(gè)鍵盤(pán)輸入钓简,該功能的編號(hào)為 0乌妒。下面的指令從鍵盤(pán)緩沖區(qū)中讀取一個(gè)鍵盤(pán)輸入汹想,并將其從鍵盤(pán)緩沖區(qū)中刪除:
????mov ah, 0
????int 16h
????結(jié)果:讀取出的數(shù)據(jù)默認(rèn)寫(xiě)到 ax 寄存器中,(ah)=掃描碼撤蚊,(al)=ASCII碼
int 16h 中斷例程的 0 號(hào)子程序的功能:
- 檢測(cè)鍵盤(pán)緩沖區(qū)中是否有數(shù)據(jù)古掏;
- 沒(méi)有則等待,繼續(xù)做第 1 步侦啸;
- 讀取鍵盤(pán)緩沖區(qū)第一個(gè)字單元中的鍵盤(pán)輸入槽唾;
- 將讀取的掃描碼送入 ah 中,ASCII 碼送入 al光涂;
- 將已讀取的鍵盤(pán)輸入從鍵盤(pán)緩沖區(qū)中刪除庞萍。
3. BIOS 的 int 9h 中斷例程和 int 16h 中斷例程是一對(duì)相互配合的程序。
- int 9h 中斷例程向鍵盤(pán)緩沖區(qū)中寫(xiě)入(int 9h 中斷例程是在有按鍵按下的時(shí)候向鍵盤(pán)緩沖區(qū)中寫(xiě)入數(shù)據(jù)忘闻,狀態(tài)鍵除外挂绰,狀態(tài)鍵是存儲(chǔ)在狀態(tài)字節(jié)中)。
- int 16h 中斷例程從鍵盤(pán)緩沖區(qū)中讀出(int 16h 中斷例程是在應(yīng)用程序?qū)ζ溥M(jìn)行調(diào)用的時(shí)候服赎,將數(shù)據(jù)從鍵盤(pán)緩沖區(qū)中讀出)葵蒂。
4. 簡(jiǎn)略示意圖
2) 練習(xí) 1:
編程,接收用戶(hù)的鍵盤(pán)輸入重虑,輸入“r”践付,將屏幕上的字符設(shè)置為紅色;輸入“g”缺厉,將屏幕上的字符設(shè)置為綠色永高;輸入“b”,將屏幕上的字符設(shè)置為藍(lán)色提针。
文件名: pro172.asm
assume cs:code
code segment
start:
mov ah, 0
int 16h ; 將數(shù)據(jù)從鍵盤(pán)緩沖區(qū)中讀出命爬,讀取出的數(shù)據(jù)默認(rèn)寫(xiě)到 ax 寄存器中,(ah)=掃描碼辐脖,(al)=ASCII碼
mov ah, 1 ; 設(shè)置 ah 存放的是字符屬性
cmp al, 'r' ; 如果對(duì)應(yīng)的 ASCII 碼是 r饲宛,則將屏幕上的字符設(shè)置為紅色
je red
cmp al, 'g'
je green
cmp al, 'b'
je blue
jmp short sret
red:
shl ah, 1
green:
shl ah, 1
blue:
mov bx, 0b800h
mov es, bx
mov bx, 1
mov cx, 2000
s:
and byte ptr es:[bx], 11111000b
or es:[bx], ah
add bx, 2
loop s
sret:
mov ax, 4c00h
int 21h
code ends
end start
3) 練習(xí) 2:
字符串的輸入,需要具備以下的功能:
(1)在輸入的同時(shí)需要顯示這個(gè)字符串嗜价;
(2)一般在輸入回車(chē)符后艇抠,字符串輸入結(jié)束;
(3)能夠刪除已經(jīng)輸入的字符久锥。文件名: pro173.asm
assume cs:code
stack segment
db 1024 dup (0) ; charstack 的子程序中使用 dw 定義字型數(shù)據(jù)家淤,所以這里應(yīng)該寫(xiě) 2^16 = 65536
stack ends
code segment
start:
mov ax, stack
mov ds, ax
mov si, 0 ; ds:si 指向字符棧空間
mov dh, 13 ; 字符串在屏幕上顯示的行數(shù)
mov dl, 32 ; 字符串在屏幕上顯示的列數(shù)
call getstr ; 調(diào)用子程序瑟由,獲取字符串的輸入
mov ax, 4c00h
int 21h
; 接收字符串輸入的子程序
getstr:
push ax
getstrs:
mov ah, 0
int 16h ; 將數(shù)據(jù)從鍵盤(pán)緩沖區(qū)中讀出絮重,讀取出的數(shù)據(jù)默認(rèn)寫(xiě)到 ax 寄存器中,(ah)=掃描碼,(al)=ASCII碼
cmp al, 20h
jb nochar ; ASCII 小于 20h青伤,說(shuō)明不是字符
mov ah, 0
call charstack ; 字符入棧
mov ah, 2
call charstack ; 顯示棧中的字符
jmp getstrs
nochar:
cmp ah, 0eh ; 退格鍵的掃描碼
je backspace
cmp ah, 1ch ; Enter 鍵的掃描碼
je enter
jmp getstrs
backspace:
mov ah, 1
call charstack ; 字符出棧
mov ah, 2
call charstack ; 顯示棧中的字符
jmp getstrs
enter:
mov al, 0
mov ah, 0
call charstack ; 0 入棧
mov ah, 2
call charstack ; 顯示棧中的字符
pop ax
ret
; 子程序:字符棧的入棧督怜、出棧和顯示
; 參數(shù)說(shuō)明:(ah)=功能號(hào),0 表示入棧潮模,1 表示出棧,2 表示顯示
; ds:si 指向字符棾帐空間
; 對(duì)于 0 號(hào)功能:(al)=入棧字符
; 對(duì)于 1 號(hào)功能:(al)=返回字符
; 對(duì)于 2 號(hào)功能:(dh)擎厢、(dl)=字符串在屏幕上顯示的行、列位置
charstack:
jmp short charstart
table dw charpush, charpop, charshow
top dw 0 ; 棧頂
charstart:
push bx
push dx
push di
push es
cmp ah, 2
ja sret ; 大于 2辣吃,則跳轉(zhuǎn)返回
mov bl, ah
mov bh, 0
add bx, bx ; table 使用 dw 定義數(shù)據(jù)动遭,所以需要 *2
jmp word ptr table[bx]
charpush:
mov bx, top
mov [si][bx], al
inc top
jmp sret
charpop:
cmp top, 0
je sret
dec top
mov bx, top
mov al, [si][bx]
jmp sret
charshow:
mov bx, 0b800h
mov es, bx
mov al, 160
mov ah, 0
mul dh ; 8 位乘法,結(jié)果放在 ax 中
mov di, ax
add dl, dl
mov dh, 0
add di, dx ; 行*160 + 列*2
mov bx, 0
charshows:
cmp bx, top
jne noempty
mov byte ptr es:[di], ' '
jmp sret
noempty:
mov al, [si][bx]
mov es:[di], al
mov byte ptr es:[di+2], ' '
inc bx
add di, 2
jmp charshows
sret:
pop es
pop di
pop dx
pop bx
ret
code ends
end start