任务:安装一个新的 int 9 中断例程,功能:在 DOS 下,按 F1 键后改变当前屏幕的显示颜色,其他的键照常处理。
1、改变屏幕的显示颜色; 改变从 B8000 开始的 4000 个字节中的所有奇地址单元中的内容,当前屏幕的显示颜色即发生改变。 mov ax , 0b800h
mov es , ax
mov bx , 1
mov cx , 2000
s: inc byte ptr es:[bx]
add bx , 2
loop s
|
2、其他键照常处理; 可以调用原 int 9 中断处理程序,来处理其他的键盘输入。 |
3、原 int 9 中断例程的入口地址保存; 因为在编写的新 int 9 中断例程中要调用原 int 9 中断例程处理键盘输入的其他细节,所以,要保存原 int 9 中断例程的入口地址。因为安装程序返回后地址将丢失,所以可以选择将地址保存在 0:200 单元处。这个地方是开辟给中断向量表的,其他程序不能访问,但是向量表用不了这么多。 |
4、新 int 9 中断例程的安装 可以从 0:204 处开始安装 |
assume cs:code
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 ax , 0
mov es , ax
mov si , offset int9 ; 安装新中断例程地址
mov di , 204h
mov cx , offset int9end- offset int9
cld
rep movsb
push es:[9*4] ; 保存原int 9中断例程入口地址
pop es:[200h]
push es:[9*4+2]
pop es:[202h]
cli ; 关可屏蔽中断
mov word ptr es:[9*4] , 204h ; 设置新的int 9中断例程入口地址
mov word ptr es:[9*4+2] , 0
sti ; 开可屏蔽中断
mov ax , 4c00h
int 21h
|
int9: push ax
push bx
push cx
push es
in al , 60h
pushf
call dword ptr cs:[200h] ; 当9号中断执行的时候(CS)=0
;这里调用原int 9中断例程,我们事先把原9号中断例程的入口地址存放在0:[200]~0:[204]
;之所以要调用原9号中断例程,是因为还要处理其它细节
;eg:扫描码加上ASCII放到键盘输入缓冲区,状态字节放到0040:17
cmp al , 3bh ; F1 键的扫描码是 3bh
jne int9ret
mov ax , 0b800h
mov es , ax
mov bx , 1
mov cx , 2000 ; 25*80=2000 一页可以存2000个字符,每个字符要存一个字符属性,25*160=4000
s: inc byte ptr es:[bx] ; 循环修改显示页面能存储的所有字符的显示属性
add bx , 2
loop s
int9ret: pop es
pop cx
pop bx
pop ax
iret
int9end: nop
code ends
end start
|
// 这是按下3次 F1 键后的显示效果;执行了一次 1.exe 再输入执行 1.exe 程序会卡死,因为第二次执行,本来代码中保存系统原来的9号中断例程入口地址现在变成保存我们新改写的中断例程,后面int9中断调用原9号中断例程处理键盘输入调用不到了,不能处理我们的键盘输入,所以系统崩溃,得重启DOS
// 这是显示一页后又回车加入新的行,再执行F1变色……
assume cs:code
stack segment
db 128 dup (0)
stack ends
code segment
start: mov ax , stack
mov ss , ax
mov sp , 128
mov ax , 4c00h
int 21h
code ends
end start
|