记录一下Int9中断。
我们从键盘输入一个按键时,会到达相关芯片的60端口;60端口会向CPU发出int9中断:告诉CPU有输入到了60端口。
int9中断处理过程,有以下三步:
- 读取60h端口中的扫描码;
- 如果是字符键的扫描码,将送入内存中的BIOS键盘缓冲区;如果是控制键和切换键的扫描码,则将其转换为状态字,写入内存中存储状态字节的单元;
- 对键盘系统进行相关控制,比如说,向相关芯片发出应答信息。
上边这个过程,可以用下边的图表示。
编写一个int9中断的例子,如下:
该程序可随意改变屏幕颜色。
assume cs:code,ss:stack,ds:data
data segment
db 128 dup(0)
data ends
stack segment stack
db 128 dup(0)
stack ends
code segment
start:
mov ax,stack
mov ss,ax
mov sp,128
call cpy_new_int9
call save_old_int9
call set_new_int9
mov ax,4c00h
int 21h
;====================================================
set_new_int9:
mov bx,0
mov es,bx
cli ;安全考虑,在处理该程序时,禁止其他可屏蔽中断;
mov word ptr es:[9*4],7E00h
mov word ptr es:[9*4+2],0 ;将新中断程序,放入0:7e00h的位置。
sti
ret
;=================================================
;保存原来的int9的地址,最后再将这个值设置为该值。
save_old_int9:
push bx
push es
mov bx,0
mov es,bx
cli
push es:[9*4] ;保存了Int9的CS和IP
pop es:[200H]
push es:[9*4+2]
pop es:[202H]
sti
pop es
pop bx
ret
;==============================================
;这是新拷贝程序
new_int9:
push ax
in al,60H ;从60h端口读取扫描码
pushf
call dword ptr cs:[200H] ;cs=0
cmp al,3BH ;判断是否为esc键,如果不是,跳过 F1的扫描码
jne int9Ret
call change_screen_color
int9Ret:
pop ax
iret
;=================================================
;方法是,让整个屏幕的字符(2000字符)的背景颜色改变。
change_screen_color:
push bx
push cx
push es
mov bx,0b800h
mov es,bx
mov bx,1 ;单数是显示的属性
mov cx,2000H
changeColor:
inc byte ptr es:[bx] ;属性自增1
add bx,2 ;
loop changeColor
pop es
pop cx
pop bx
ret
new_int9_end:
nop
;============================================
;拷贝程序,新中断拷贝到0:07e00h的位置
cpy_new_int9:
mov bx,cs
mov ds,bx
mov si,OFFSET new_int9 ;设置程序源位置
mov bx,0
mov es,bx
mov di,7e00h ;设置目的地
mov cx,OFFSET new_int9_end - OFFSET new_int9 ;cx 计数
cld ;自增1
rep movsb ; 将ds:[OFFSET new_int9]按字节拷贝到es:[7e00h]位置
ret
code ends
end start