求教,替换了自己的键盘中断服务程序之后,不知为何恢复不了。
我在写一个关于中断控制芯片 8259A 的汇编程序。其中我替换了系统的键盘中断服务程序(中断向量号是 09h),执行完任务之后恢复系统中断始终不行。所以返回 DOS 后键盘无法输入(是 OS X 下的 DOSBox)。我自己对照课本的类似代码研究一天了,没看出问题,请各位赐教。
以下是我的部分代码:
汇编 键盘 中断
.model small
.stack
.data
intmsg0db 'IR0 = 0 in ISR',0dh,0ah,0
intmsg1db 'IR0 = 1 in ISR',0dh,0ah,0
counterdb 0
isrdb 0
myseg8dw 0
myoffset8dw 0
myseg9dw 0
myoffset9dw 0
.code
start:
mov ax,@data
mov ds,ax
mov ax,3508h; 获取原 08h 中断服务程序入口
int 21h
mov myseg8, es; 保存原 08h 中断服务程序入口
mov myoffset8, bx
mov ax,3509h; 获取原 09h 中断服务程序入口
int 21h
mov myseg9, es; 保存原 09h 中断服务程序入口
mov myoffset9, bx
cli
push ds
mov ax,seg new08h; 重设 08h 中断(定时器)
mov ds,ax
mov dx,offset new08h
mov ax,2508h
int 21h
mov ax,seg new09h; 重设 09h 中断(键盘)
mov ds,ax
mov dx,offset new09h
mov ax,2509h
int 21h
pop ds
; 设置允许 IR0、IR1 中断
in al,21h
push ax
and al,0fch; 允许 IRQ0 与 IRQ1,IRQ0 比 IRQ1 的优先级高
out 21h,al
mov counter,0
sti
start1:
cmp counter,10 ; 循环十次处理 08h 中断
jb start1
cli
pop ax
out 21h,al
mov ax, myseg9 ; 恢复 09h 中断服务程序
mov ds, ax
mov dx, myoffset9
mov ax, 2509h
int 21h
mov ax, myseg8 ; 恢复 08h 中断服务程序
mov ds, ax
mov dx, myoffset8
mov ax, 2508h
int 21h
sti
mov ax,4c00h
int 21h
new08hproc
cli
push ax
push bx
push ds
mov al,68h; 向 ocw3 写入,设置特殊屏蔽模式
out 20h,al
in al,21h
or al,01h; 屏蔽 IR0
out 21h,al; 向 ocw1 写入
mov al,00001011b; 向 ocw3 写入,下一读指令,读 ISR
out 20h,al
in al,20h
mov isr,al; 保存从 ISR 读出的值
sti
mov ax,@data
mov ds,ax
test isr,01h
inc counter
jnz isr1
mov si,offset intmsg0
call dpstri
jmp end08h
isr1:
mov si,offset intmsg1
call dpstri
end08h:
cli
in al,21h
and al,0feh; 允许 IR0
out 21h,al; 向 ocw1 写入
sti
mov al,20h; 发送 EOI
out 20h,al
pop ds
pop bx
pop ax
iret
new08hendp
new09h proc
iret
new09h endp
dpstriproc
push ax
push bx
dps1:
lodsb
cmp al,0
jz dps2
mov bx,0
mov ah,0eh
int 10h
jmp dps1
dps2:
pop bx
pop ax
ret
dpstriendp
end start
[解决办法]
首先你最后的恢复中断向量时的做法是错误的
mov ax, myseg9 ; 恢复 09h 中断服务程序
mov ds, ax
mov dx, myoffset9 ; 上面设置 ds 指向了原 int9 的段,不再是自己的数据段了,
; 所以这里获得的 dx 就是错误的。下面的 int8 的恢复也一样
mov ax, 2509h
int 21h