改写int 9中断例程
0 问题概述
修改“int 9”号中断例程的功能,在DOS中按下ESC键后改变屏幕的显示颜色,其他的键照原有功能处理
要解决的问题:
(1)改变屏幕的显示颜色:一个屏幕是由4000个字节组成,偶数对应的字节存放字符的ascll码,奇数对应的字节存放的字符的属性(该字节左边一个字节内容的属性),所有总共要修改2000个属性字节
(2)原“int 9”中断例程入口地址保存在"0:200"处,共两个字,低字单元存放偏移地址,高字单元存放段地址,而“新int 9”中断例程的入口地址则替换"旧int 9"的入口地址
(3)“新int 9”中断例程的安装,其在地址0:204处开始安装到内存中
1 代码实现1–“新int 9”中断例程
intN9:
;保存原先寄存器内容
push ax
push es
push bx
push cx
pushf
pushf
pop ax
and ah,11111100b ;psw标志寄存器的TF和IF位置0,表示关"闭陷阱标志"和"中断响应"
push ax
popf
;调用原来"int 9"中断例程
call dword ptr cs:[200]
;判断是否是ESC键,是就往下执行,否则跳转到intS9处
in al,60h
cmp al,1;ESC键的扫描码:1
jne intS9
;修改屏幕颜色
mov ax,0B800h
mov es,ax
mov bx,1
mov cx,2000
s: inc byte ptr es:[bx]
add bx,2 ;保证bx始终为奇数
loop s
;恢复原来寄存器的内容
intS9: pop cx
pop bx
pop es
pop ax
iret
intEnd9: nop ;长度结束标志,新中断例程字节数 = offset intEnd9 - offset intN9
2 保存原来“int 9”中断例程的入口地址到0:200
push es:[9*4+2]
pop es:[202]
push es:[9*4]
pop es:[200]
备注:es的内容为0
3 复制"新int 9"中断程序到地址0:204
mov cx,offset intEnd9 - offset intN9 ;计算新int 9中断例程的程序长度(占的字节数)
cld ;使psw标志寄存器的DF位置0,
rep movsb ;按字节批量复制新中断例程到内存地址0:200处
备注:此时 (ds)=(cs)、(si)=offset intN9;(es)=0、(di)=204
4 "新int 9"中断例程的入口地址替换原来的例程的入口地址(修改中断向量表)
cli ;设置IF=0,关闭中断响应,即执行下面两行指令期间cpu不响应中断请求
mov word ptr es:[9*4],204
mov word ptr es:[9*4+2],0
sti ;设置IF=1,恢复中断响应
5 完整代码
assume cs:code,ss:stack
stack segment
db 128 dup(0)
stack ends
code segment
;初始化寄存器
start: mov ax,stack
mov ss,ax
mov sp,128
push cs
pop ds
mov si,offset intN9
mov ax,0
mov es,ax
mov di,204
;保存原来int9号的入口地址到0:200地址
push es:[9*4+2]
pop es:[202]
push es:[9*4]
pop es:[200]
;复制新中断程序到0:204地址
mov cx,offset intEnd9 - offset intN9
cld
rep movsb
;修改中断向量表中原来的入口地址为新的入口地址
cli
mov word ptr es:[9*4],204
mov word ptr es:[9*4+2],0
sti
mov ax,4c00h
int 21h
;新int9号程序,保留原有int9号功能,增加按ESC键改变屏幕颜色
intN9:
push ax
push es
push bx
push cx
pushf
pushf
pop ax
and ah,11111100b
push ax
popf
call dword ptr cs:[200]
;判断是否是ESC键,是就修改颜色,否则保持原来键的功能
in al,60h
cmp al,1;ESC键的扫描码:1
jne intS9
mov ax,0B800h
mov es,ax
mov bx,1
mov cx,2000
s: inc byte ptr es:[bx]
add bx,2
loop s
intS9: pop cx
pop bx
pop es
pop ax
iret
intEnd9: nop
code ends
end start