写这篇博客的时候,已经快晚上12点了;至于为什么这个时候写,我也不想,无奈失眠。PS:半个小时解决
实验15 安装新的int 9中断例程
安装一个新的 int 9中断例程,功能:在DOS下,按下“A”键后,除非不再松开,如果松开,就显示满屏的“A”,其他的键照看处理。
提示,按下一个键时产生的扫描称为通码,松开一个键产生的扫描码称为断码。断码=通码+80H
这里的程序,其实只要在之前的地方稍微改动下就行了。
我简单的分析下:在按下键盘的一个键时(不松开),会产生一个扫描码(通码),此时的通码会被送入主板上的相关接口的芯片的寄存器中,该寄存器的端口地址为60h。(这些是由硬件自动完成的)
同样的在释放的时候,也会产生一个扫描码(断码),也会被送到端口为60h的寄存器,就是👆说那个,一样的。
当我们按下键时,为松开时,扫描一直都是按下的那个键的通码,这时cpu(如果IF=1),会响应中断,转去执行int9中断例程。
当未修改int9中断例程的时候,按下一个键不松开,键上的内容会一直连续不断的显示在屏幕上,直到你松开那个键。而这些在原来的int9 中断例程中已经实现了,我们不用管。可以直接调用
👇接着我们考虑另外一个问题 /松开,显示满屏的“A”/ 当我们按下A键时,应该执行的时原来的int9中断例程。当松开时,显示满屏的A(这个就新的中断例程),那我们只需要,检测松开时的扫描码(断码)是否为A的断码即可。
具体代码如下
assume cs:code
stack segment
db 128 dup(0)
stack ends
code segment
start: mov sp,128
mov ax,stack
mov ss,ax
mov si,offset int9
mov ax,0
mov es,ax
push cs
pop ds
mov di,204h
mov cx,offset int9end-offset int9
cld
rep movsb
push es:[9*4]
pop es:[200h]
push es:[9*4+2]
pop es:[202h]
cli ; IF设置为0屏蔽中断
mov word ptr es:[9*4],204h ;偏移地址
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]
cmp al,9Eh ;A的按下的扫描码为1E(通码),9E(断码)
jne int9ret
mov ax,0b800h
mov es,ax
mov cx,2000
mov bx,0
s: mov byte ptr es:[bx],'A'
add bx,2
loop s
int9ret:pop es
pop cx
pop bx
pop ax
iret ;之前忘记加了,就会导致不能返回到源程序
int9end:nop
code ends
end start
下面展示演示过程
由于不能直接上传视频,所以只好链接一下下喽!麻烦各位了,当然嫌麻烦可以不用看,自己上机试试啊!