替换INT 9 ISR时程序崩溃,但链式调用原ISR无异常
嘿,我懂你这种想彻底接管键盘中断的需求——那些常见示例都在链式调用原ISR、依赖BIOS的INT 16h服务,确实没法满足你的特殊场景。我来给你梳理下完全替换INT 9 ISR的核心要点和实现步骤:
核心实现步骤
1. 先存好原INT 9向量(可选但强烈建议)
虽然你不想链式调用原ISR,但提前保存它绝对是个好习惯——万一后续要恢复系统状态,或者调试时出问题能快速回滚。用这段代码获取并存储原向量:
mov ah, 35h mov al, 09h int 21h ; 原ISR的段地址存在es,偏移量在bx,把它们存到自定义变量里 mov [old_int9_offset], bx mov [old_int9_segment], es
记得执行前用cli关中断,操作完再用sti开中断,避免向量被中途修改。
2. 安装你的自定义INT 9 ISR
接下来把你的中断处理程序挂到INT 9向量上,同样要先关中断防止竞态:
cli mov ah, 25h mov al, 09h mov dx, offset my_custom_int9 push cs pop ds ; 确保ds指向当前代码段,因为dx是程序内的偏移量 int 21h sti
3. 自定义ISR的核心逻辑
你的ISR要直接和硬件打交道,完全绕开BIOS的处理流程,这里有几个必须做的事:
- 读取
60h端口获取键盘扫描码(通码是按键按下,断码是通码加80h,比如Esc键通码是01h,断码是81h) - 编写你自己的按键处理逻辑(比如判断扫描码执行对应操作)
- 必须发送EOI(中断结束信号):向
20h端口写入20h,告诉PIC中断已经处理完成,不然系统会一直收到键盘中断,直接死机!
示例代码大概是这样:
my_custom_int9: push ax bx cx dx ; 保存用到的寄存器,避免破坏上层程序状态 in al, 60h ; 读取扫描码 ; 这里写你的按键处理逻辑,比如判断扫描码执行对应操作 mov al, 20h out 20h, al ; 发送EOI信号 pop dx cx bx ax ; 恢复寄存器 iret ; 中断返回
4. 必看的注意事项
- 寄存器保护:ISR里用到的通用寄存器一定要push进去,处理完再pop出来,不然会打乱调用中断前的程序状态
- ISR要尽量轻量化:别在里面做耗时操作,比如调用DOS的
int 21h功能(除非是极简单的操作),不然会拖慢整个系统的响应 - 退出前恢复原ISR:程序结束时一定要把之前保存的原INT 9向量恢复回去,不然其他程序或者系统本身会出现异常
内容的提问来源于stack exchange,提问作者bad
相关产品推荐
相关产品推荐

