CPU不論處理內中斷仍是外中斷都是經過中斷類型碼來選擇要執行的中斷例程。外中斷可分爲可屏蔽和不可屏蔽,當IF=0時,會屏蔽掉可屏蔽中斷。oop
以鍵盤輸入爲例。當按下一個鍵時,就會產生一個掃描碼,並傳到端口60h,此時相關芯片會向CPU發送中斷類型碼爲9的可屏蔽中斷。spa
端口的讀寫指令是 in/out。這裏不作具體展開,假設要讀取端口60h的數據,可用 in al,60h。code
假設如今要在int 9中斷例程的基礎上加點東西,好比但願按下esc鍵後改變屏幕輸出。blog
可行的思路是,修改中斷向量表中9號中斷例程的入口地址爲子程序的地址,隊列
當IF = 1且有鍵盤輸入時,進入到子程序,子程序要先執行原先的9號中斷例程(先pushf,再call)。所以要先將原先的9號中斷例程的地址記錄下來。注意每一個子程序/中斷例程內部結束處都會有ret/iret,因此這裏執行了pushf和call,中斷例程內部結束處會有iret來執行ret和popf。class
執行完中斷例程後再執行添加的指令。完整程序以下基礎
assume cs:code
stack segment
db 128 dup(0) stack ends data segment dw 0,0 data ends code segment start: mov ax,stack mov ss,ax mov sp,128 mov ax,data mov ds,ax mov ax,0 mov es,ax push es:[9*4] pop ds:[0] push es:[9*4+2] pop ds:[2] pushf pop ax mov word ptr es:[9*4],offset int9 mov es:[9*4+2],cs mov ax,0b800h mov es,ax mov ah,'a' s: mov es:[160*12+40*2],ah call delay inc ah cmp ah,'z' jna s mov ax,4c00h int 21h delay: push ax push dx mov dx,10 mov ax,0 s1: sub ax,1 sbb dx,0 cmp ax,0 jne s1 cmp dx,0 jne s1 pop dx pop ax ret int9: push ax push bx push es in al,60h pushf call dword ptr ds:[0] cmp al,1 jne int9ret mov ax,0b800h mov es,ax inc byte ptr es:[160*12+40*2+1] int9ret: pop es pop bx pop ax iret code ends end start
int 9h中斷例程是在有鍵按下的時候向鍵盤緩衝區寫入數據,這裏的鍵盤緩衝區是雙向隊列,可存放15個鍵盤輸入,每一個鍵盤輸入包含掃描碼和ASCII碼(這裏會檢查狀態字節,結合原字符獲得ASCII碼)。對應的,若是要從鍵盤緩衝區讀取數據,可用int 16h,其功能號爲0(有的中斷例程須要功能號或一些其餘的參數),指令爲程序
mov ah,0call
int 16h數據
經過該語句,ax被賦值,其中(ah) = 掃描碼,(al) = ASCII碼。
假設如今想經過按下r/g/b鍵令顯示區的字符全爲紅/綠/藍,
assume cs:code code segment start: mov ah,0 int 16h mov ah,1 cmp al,'r' 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