文章目录
前言
本文是王爽老师《汇编语言》(第四版) 第十五章 实验15 安装新的int 9中断例程(按下并松开A键后显示满屏的A,其它键照常处理) 的分析及代码。
一、实验任务
安装一个新的int 9中断例程,功能:在dos下,按下“A”键后,除非不再松开,如果松开,就显示满屏幕的“A”,其它的键照常处理。
最终效果如图,按下并松开A键后显示满屏的“A”。
二、思路分析
实现的整体思路:
1.写一个新的9号中断例程,其中调用系统BIOS的9号中断例程,之后再对“A”键输入进行处理;
2.将自定义的9号中断例程安装在系统0:204H处,而BIOS的9号中断例程入口地址,存放在0:200H处。
1.编写9号中断例程
这个自定义的中断例程要做的事情:
① 从端口读取键盘输入;
②调用系统提供的int 9H中断例程,进行与硬件相关的处理;
③如果输入的是“A”,那么就进行处理,使屏幕上所有字符都变为“A”,即ASCII码的41H。
注意:调用BIOS的中断例程时应该用“dword ptr”而不是“word ptr”。
代码如下。
do9H: ;自定义9号中断例程 功能:松开A键则显示满屏幕的A,其它键照常处理
;参数:无
;返回:无
push ax
push bx
push es
push cx
;1.从60H端口接收键盘输入
in al,60H
;2.调用BIOS的9号中断例程
pushf ;将标志寄存器压入栈
call dword ptr cs:[200H] ;0:200H处存放BIOS的9号中断例程的入口地址
;3.对“A”键进行处理
cmp al,9EH ;A的通码为1EH,断码为9EH
jne do9H_iret
mov ah,'A' ;若按下的是A键,则显示满屏的A
mov bx,0B800H
mov es,bx
mov bx,0 ;当前字符偏移地址
mov cx,2000 ;一屏能显示2000个字符
s_do9H:
mov es:[bx],ah
add bx,2
loop s_do9H
do9H_iret: ;程序返回
pop cx
pop es
pop bx
pop ax
iret
do9H_end:nop
2.安装9号中断例程
安装中断例程的代码之前写过,但这里多了一步,要在自定义的中断例程中调用BIOS的中断例程,因此要写一个新的install子程序。
注意,因为BIOS提供的int 9H中断例程还要被调用,所以要先将BIOS的中断例程入口地址保存起来(中断向量表中取出,保存到0:200H处),之后再将自定义的9号中断例程的入口地址写入中断向量表。
代码如下。
install: ;功能:将自定义的9号中断例程安装在0:204H处,并将BIOS的9号中断例程入口地址复制在0:200H处
;参数:无
;返回:无
push ax
push ds
push si
push es
push di
push cx
;1.将自定义的9号中断例程程序段复制到0:204H处
push cs ;ds:si指向要复制的源地址起始处
pop ds
mov si,offset do9H
mov ax,0 ;es:di指向复制的目标地址起始处
mov es,ax
mov di,204H
mov cx,offset do9H_end - offset do9H ;要复制的数据长度
cld ;设置DF=0,正向传输
rep movsb
;2.将BIOS的9号中断例程入口地址复制到0:200H处
mov ax,0
mov es,ax
push es:[9*4] ;偏移地址
pop es:[200H]
push es:[9*4+2] ;段地址
pop es:[202H]
;3.将自定义的9号中断例程的入口地址添加到中断向量表中
cli ;设置IF=0,不响应可屏蔽中断 相当于一个锁,避免地址设置错误
mov word ptr es:[9*4],204H ;偏移地址
mov word ptr es:[9*4+2],0H ;段地址
sti ;设置IF=1,响应可屏蔽中断
pop cx
pop di
pop es
pop si
pop ds
pop ax
ret
三、完整代码
最终效果还是不错的,挺好玩,哈哈。
自定义的中断例程中处理的是“A”的断码,其实A键和其它键还是可以正常使用(因为一般键入字符的功能检测的都是键盘输入的通码而不是断码),只不过当松开A键以后屏幕上全是“A”,覆盖了原先的显示内容。
如果想要清屏,那么需要“cls”命令然后回车,搞定。
以下是完整代码。
assume cs:code
stack segment
db 64 dup(0)
stack ends
code segment
start:
mov ax,stack ;设置栈顶
mov ss,ax
mov sp,40H
call install
mov ax,4c00H
int 21H
install: ;功能:将自定义的9号中断例程安装在0:204H处,并将BIOS的9号中断例程入口地址复制在0:200H处
;参数:无
;返回:无
push ax
push ds
push si
push es
push di
push cx
;1.将自定义的9号中断例程程序段复制到0:204H处
push cs ;ds:si指向要复制的源地址起始处
pop ds
mov si,offset do9H
mov ax,0 ;es:di指向复制的目标地址起始处
mov es,ax
mov di,204H
mov cx,offset do9H_end - offset do9H ;要复制的数据长度
cld ;设置DF=0,正向传输
rep movsb
;2.将BIOS的9号中断例程入口地址复制到0:200H处
mov ax,0
mov es,ax
push es:[9*4] ;偏移地址
pop es:[200H]
push es:[9*4+2] ;段地址
pop es:[202H]
;3.将自定义的9号中断例程的入口地址添加到中断向量表中
cli ;设置IF=0,不响应可屏蔽中断 相当于一个锁,避免地址设置错误
mov word ptr es:[9*4],204H ;偏移地址
mov word ptr es:[9*4+2],0H ;段地址
sti ;设置IF=1,响应可屏蔽中断
pop cx
pop di
pop es
pop si
pop ds
pop ax
ret
do9H: ;自定义9号中断例程 功能:松开A键则显示满屏幕的A,其它键照常处理
;参数:无
;返回:无
push ax
push bx
push es
push cx
;1.从60H端口接收键盘输入
in al,60H
;2.调用BIOS的9号中断例程
pushf ;将标志寄存器压入栈
call dword ptr cs:[200H] ;0:200H处存放BIOS的9号中断例程的入口地址
;3.对“A”键进行处理
cmp al,9EH ;A的通码为1EH,断码为9EH
jne do9H_iret
mov ah,'A' ;若按下的是A键,则显示满屏的A
mov bx,0B800H
mov es,bx
mov bx,0 ;当前字符偏移地址
mov cx,2000 ;一屏能显示2000个字符
s_do9H:
mov es:[bx],ah
add bx,2
loop s_do9H
do9H_iret: ;程序返回
pop cx
pop es
pop bx
pop ax
iret
do9H_end:nop
code ends
end start
总结
本文是王爽老师《汇编语言》(第四版) 第五章 实验15 安装新的int 9中断例程的分析及代码。这个实验比较简单有趣。