|
zhushouqqq
初级用户
 
积分 32
发帖 13
注册 2008-12-2
状态 离线
|
『楼 主』:
关于汇编改写中断入口地址 的问题。
[已使用 LLM 解释]
在程序运行期间 修改了int9的入口地址 程序结束 恢复int9的入口地址
程序的执行从结果上看是正常的 结束后,键盘就锁住了。
以下是代码。
assume cs:codesg,ds:datasg,ss:stacksg
stacksg segment
db 128 dup(0)
stacksg ends
datasg segment
int9ip dw 0
int9cs dw 0
datasg ends
codesg segment
start:
mov ax,datasg
mov ds,ax
mov ax,0
mov es,ax
mov si,0
mov dx,es:[9*4]
mov word ptr int9ip,dx
mov dx,es:[9*4+2]
mov word ptr int9cs,dx ;保存当前的int 9的中断向量
;
mov word ptr es:[9*4],offset int99
mov word ptr es:[9*4+2],cs ;设置int 9中断向量
mov ax,0b800h
mov es,ax
mov di,160*12+2*40 ;第13行中间开始
mov cx,10
;
mov al,'a'
mov ah,7ch ;颜色
mov es:[di+1],ah
;
s:
mov es:[di],al
call time
inc al
loop s ;循环显示
mov dx,int9ip
mov word ptr es:[9*4],dx
mov dx,int9cs
mov word ptr es:[9*4+2],dx ;恢复int 9中断向量
mov ax,4c00h
int 21h
;----------------------------------
int99: ;到这里 CS IP 标志寄存器 已经由硬件完成入栈
mov ah,0fch
mov byte ptr es:[di+1],ah ;恢复向量表
iret
;----------------------------------
;用于延时
time proc
push ax
push bx
mov bx,1000h
mov ax,0
s1:
sub ax,1
sbb bx,0
cmp ax,0
jne s1
cmp bx,0
jne s1
pop bx
pop ax
ret
time endp
codesg ends
end start
继续研究。。。
LLM 解释
问题分析:键盘锁住的根本原因
您的程序在修改 int 9 中断向量后未能正确处理键盘硬件响应,导致键盘控制器始终处于等待状态,表现为"键盘锁住"。具体问题如下:
-
中断处理程序不完整:自定义的
int99 仅修改了显示颜色,未执行键盘中断必须的硬件操作
-
缺少EOI信号:未向8259A PIC发送中断结束命令,导致后续中断被屏蔽
-
未读取键盘扫描码:未从端口60h读取扫描码,键盘控制器无法接收新按键
正确解决方案
1. 完整的中断处理程序实现
assume cs:codesg,ds:datasg,ss:stacksg
stacksg segment
db 128 dup(0)
stacksg ends
datasg segment
int9ip dw 0 ;保存原中断向量IP
int9cs dw 0 ;保存原中断向量CS
datasg ends
codesg segment
start:
mov ax,datasg
mov ds,ax
mov ax,stacksg
mov ss,ax
mov sp,128 ;初始化栈段,确保中断处理时堆栈可用
;保存原int9中断向量
cli ;关中断,避免保存向量过程被中断打断
mov ax,0
mov es,ax
mov dx,es:[9*4]
mov int9ip,dx
mov dx,es:[9*4+2]
mov int9cs,dx
;设置新int9中断向量
mov word ptr es:[9*4],offset int99
mov word ptr es:[9*4+2],cs
sti ;恢复中断
;显示字符部分
mov ax,0b800h
mov es,ax
mov di,160*12+2*40 ;第13行中间位置
mov cx,10
mov al,'a'
mov ah,7ch ;初始颜色
mov es:[di+1],ah ;设置颜色属性
s: mov es:[di],al ;显示字符
call time ;延时
inc al
loop s
;恢复原中断向量
cli ;关中断,确保恢复向量过程安全
mov dx,int9ip
mov es:[9*4],dx
mov dx,int9cs
mov es:[9*4+2],dx
sti ;恢复中断
mov ax,4c00h
int 21h
;----------------------------------
;自定义int9中断处理程序
int99:
push ax ;保护寄存器
push bx
push es
;读取键盘扫描码
in al,60h ;从8042端口读取扫描码
;调用原int9中断处理程序
pushf ;将标志寄存器入栈,模拟中断调用环境
call dword ptr ds:[int9ip] ;调用原中断处理(CS:IP)
;自定义处理 - 修改显示颜色
mov ax,0b800h
mov es,ax
mov byte ptr es:[di+1],0fch ;修改颜色属性
pop es ;恢复寄存器
pop bx
pop ax
iret ;中断返回
;----------------------------------
;延时子程序
time proc
push ax
push bx
mov bx,1000h
mov ax,0
s1: sub ax,1
sbb bx,0
cmp ax,0
jne s1
cmp bx,0
jne s1
pop bx
pop ax
ret
time endp
codesg ends
end start
2. 关键修复点说明
-
堆栈初始化:增加了栈段初始化,确保中断处理时堆栈操作安全
-
中断开关控制:在修改中断向量时使用
cli/sti 保护,避免竞态条件
-
完整中断处理流程:
- 读取键盘扫描码 (
in al,60h )
- 调用原中断处理程序 (
call dword ptr ds:[int9ip] )
- 添加自定义功能
-
寄存器保护:使用
push/pop 保护所有修改过的寄存器
3. 中断处理的技术细节
DOS环境下修改硬件中断(int 08h-0fh )需特别注意:
-
硬件中断响应流程:
- CPU收到中断请求→自动关中断→压入FLAGS、CS、IP
- 执行中断处理程序→需手动发送EOI信号(8259A控制器)
-
原中断调用方法:
pushf ;模拟中断过程,使TF、IF标志正确传递
call dword ptr cs:old_int9 ;调用原中断处理程序
而非直接 jmp ,因为原中断可能依赖标志寄存器状态
-
兼容性考虑:
- 对于AT以上机型,需处理8042键盘控制器的A20地址线问题
- 某些DOS系统可能使用共享中断处理,直接替换可能导致冲突
4. 调试建议
若仍有问题,可采用以下调试方法:
-
在中断处理程序中添加端口调试输出:
mov al,20h ;发送EOI命令到主8259A
out 20h,al
-
使用DEBUG工具单步跟踪中断向量修改过程:
-g=start ;运行到start标签
-d 0:36 39 ;查看int9中断向量(0:36-0:39)
-
验证堆栈使用:在中断处理前后检查SP值是否一致
通过以上修改,程序将正确处理键盘中断,结束后也不会导致键盘锁住。
|
|
2008-12-3 18:26 |
|
|
本是
银牌会员
    
积分 2221
发帖 789
注册 2005-1-27
状态 离线
|
『第 2 楼』:
[已使用 LLM 解释]
你的问题出在这段程序上,你的ES被替换后未做现场保护,只要在前面加PUSH ES,在后面加POP ES就可以了。我在编VtMagiC.com时也有过如此疏漏导致的调试多次失败。汇编就是这样的!所以人家要用VB、VC啦!
mov ax,0b800h
mov es,ax
mov di,160*12+2*40 ;第13行中间开始
mov cx,10
;
mov al,'a'
mov ah,7ch ;颜色
mov es:[di+1],ah
;
s:
mov es:[di],al
call time
inc al
loop s ;循环显示
LLM 解释
汇编中断入口地址改写中的现场保护问题分析
问题定位
您指出的ES 寄存器未保护的问题确实是汇编程序设计中的常见错误。在这段显存操作代码中,ES 被修改为0B800h (文本模式显存段地址),但未考虑对原有ES 值的保存与恢复。若此代码运行在中断服务程序(ISR)或多任务环境中,会导致后续依赖ES 的操作使用错误的段地址,引发内存访问异常或数据损坏。
正确的现场保护实现
push es ; 保存原ES寄存器值
push ax ; 保护AX(可选,取决于上下文)
mov ax, 0b800h ; 设置显存段地址
mov es, ax
mov di, 160*12 + 2*40 ; 计算显存偏移量(第13行第40列)
mov cx, 10 ; 设置循环次数
mov al, 'a' ; 初始字符
mov ah, 7ch ; 属性字节(高4位背景:7=灰, 低4位前景:c=亮红)
mov es:[di+1], ah ; 写入属性(仅首次?循环中未更新)
s:
mov es:[di], al ; 写入字符
call time ; 延时/等待(需确保此调用不破坏寄存器)
inc al ; 下一个字符
add di, 2 ; 移动到下一个字符位置(每个字符占2字节)
loop s ; 循环10次
pop ax ; 恢复AX(若之前保存)
pop es ; 恢复原ES寄存器值
关键改进点说明
-
寄存器保护:使用
PUSH/POP 对ES 进行完整保护,符合中断服务程序设计规范
-
显存地址计算:
- 文本模式显存按
行×160 + 列×2 计算偏移量
- 每行80字符×2字节=160字节,12行偏移为
160×12
- 40列偏移为
2×40 ,总计160×12+2×40=1920+80=2000 (07D0h)
-
循环逻辑修正:原代码缺少
DI 递增操作,添加add di, 2 使字符依次显示
-
属性字节处理:当前仅设置一次属性,若需不同颜色需在循环内更新
AH
中断处理特殊考量
若此代码用于改写中断向量(如时钟中断08h),还需额外保护更多寄存器:
push ax bx cx dx si di es ds ; 保护所有通用寄存器
pushf ; 保护标志寄存器
; 显存操作代码...
popf ; 恢复标志寄存器
pop ds es di si dx cx bx ax ; 恢复寄存器
iret ; 中断返回(而非ret)
兼容性说明
- 对于8086/8088处理器,需确保
PUSH 的寄存器数量为偶数
- 在实模式下,段寄存器操作需注意特权级,但DOS环境通常运行在Ring 0
-
time 子程序应避免使用未保护的寄存器,或在调用前额外保护
汇编语言虽对寄存器管理要求严格,但通过规范的现场保护机制可确保系统稳定性。这种底层控制能力正是汇编在系统编程中的价值所在,与VB/VC等高级语言的内存管理模式形成互补。
|

my major is english----my love is dos----my teacher is the buddha----my friends--how about U |
|
2008-12-3 21:16 |
|
|
zhushouqqq
初级用户
 
积分 32
发帖 13
注册 2008-12-2
状态 离线
|
『第 3 楼』:
[已使用 LLM 解释]
恩 ES确实没有保护好
以下是改后的代码 我全贴出来吧, 复制过去,编译下就能运行
我想实现的功能是这样的, 在逐个显示字符期间, 如果有键盘按键。就改变原来的字符颜色。 并用改写int 9 中断的方式去实现。
assume cs:codesg,ds:datasg,ss:stacksg
stacksg segment
db 128 dup(0)
stacksg ends
datasg segment
int9ip dw 0
int9cs dw 0
datasg ends
codesg segment
start:
mov ax,datasg
mov ds,ax
mov ax,0
mov es,ax
mov si,0
mov dx,es:[9*4]
mov word ptr int9ip,dx
mov dx,es:[9*4+2]
mov word ptr int9cs,dx ;保存当前的int 9的中断向量
;
mov word ptr es:[9*4],offset int9
mov word ptr es:[9*4+2],cs ;设置int 9中断向量
push es
mov ax,0b800h
mov es,ax
mov di,160*12+2*40 ;第13行中间开始
mov cx,10
;
mov al,'a'
mov ah,7ch ;颜色
mov es:[di+1],ah
;
s:
mov es:[di],al
call time
inc al
loop s ;循环显示
pop es
mov dx,int9ip
mov word ptr es:[9*4],dx
mov dx,int9cs
mov word ptr es:[9*4+2],dx ;恢复int 9中断向量
mov ax,4c00h
int 21h
;----------------------------------
int9: ;到这里 CS IP 标志寄存器 已经由硬件完成入栈
mov ah,0fch
mov byte ptr es:[di+1],ah ;恢复向量表
iret
;----------------------------------
;用于延时
time proc
push ax
push bx
mov bx,1000h
mov ax,0
s1:
sub ax,1
sbb bx,0
cmp ax,0
jne s1
cmp bx,0
jne s1
pop bx
pop ax
ret
time endp
codesg ends
end start
程序运行 和第一次的结果一样, 在显示字符期间按键盘,字符颜色就改变。 但是,程序运行结束 键盘就不能用了,输入不了字符了。
另外,我在time子程序里 S标号的上一句加了 int 9让程序自身产生中断。 运行结果是,字符的颜色改变,键盘能用。 这就奇怪了直接在程序里写int 9和按键触发的int 9应该一样呀 都是是cs ip 寄存器 入栈。iret 恢复。
LLM 解释
问题分析与解决方案
1. 键盘无法使用的根本原因
您的中断处理程序未完成键盘中断的完整处理流程,导致键盘控制器始终处于等待状态。具体问题:
-
未读取键盘扫描码:硬件产生键盘中断后,必须从端口
60h 读取扫描码,否则键盘控制器会持续发送中断请求
-
未向8259A发送EOI:未执行
out 20h, al 命令通知中断控制器中断处理完成
-
未调用原BIOS INT 9处理程序:您的处理程序完全替换了BIOS的键盘处理逻辑,导致系统无法处理按键的后续操作(如ASCII码转换)
2. 程序内int 9 与硬件触发中断的区别
-
程序内
int 9 :仅模拟了中断调用流程,但不会触发真实硬件操作(无需读取扫描码和EOI)
-
硬件触发中断:由键盘控制器发起,必须完成完整的硬件交互流程
3. 修正后的代码
assume cs:codesg, ds:datasg, ss:stacksg
stacksg segment
db 128 dup(0)
stacksg ends
datasg segment
int9ip dw 0 ; 保存原INT9偏移地址
int9cs dw 0 ; 保存原INT9段地址
color_flag db 0 ; 颜色改变标志
datasg ends
codesg segment
start:
mov ax, datasg
mov ds, ax
mov ax, stacksg
mov ss, ax
mov sp, 128 ; 初始化栈段
; 保存原INT9中断向量
mov ax, 0
mov es, ax
push es:[9*4]
pop int9ip
push es:[9*4+2]
pop int9cs
; 设置新INT9中断向量
cli ; 关中断,避免设置向量时被中断打断
mov word ptr es:[9*4], offset int9
mov word ptr es:[9*4+2], cs
sti ; 开中断
; 初始化显示参数
mov ax, 0b800h
mov es, ax ; ES指向显存
mov di, 160*12 + 2*40 ; 第13行中间位置
mov cx, 10 ; 显示10个字符
mov al, 'a'
mov ah, 7ch ; 初始颜色
display_loop:
mov es:[di], al ; 显示字符
mov es:[di+1], ah ; 显示颜色
; 检查颜色标志并更新
cmp color_flag, 1
jne no_change
mov ah, 0fch ; 改变后的颜色
mov color_flag, 0 ; 重置标志
no_change:
call delay ; 延时
inc al ; 下一个字符
add di, 2 ; 下一个显示位置
loop display_loop
; 恢复原INT9中断向量
cli
mov ax, 0
mov es, ax
push int9ip
pop es:[9*4]
push int9cs
pop es:[9*4+2]
sti
mov ax, 4c00h
int 21h
; 自定义INT9中断处理程序
int9:
push ax
push bx
push es
; 读取键盘扫描码
in al, 60h ; 必须读取端口60h,否则键盘锁死
; 调用原BIOS INT9处理程序
pushf ; 将标志寄存器入栈,模拟中断过程
call dword ptr ds:[int9ip] ; 调用原INT9 (CS:IP = int9cs:int9ip)
; 检查是否为按键按下(扫描码最高位为0)
and al, 80h
jnz int9_ret ; 如果是释放扫描码(最高位1),不处理
; 设置颜色改变标志
mov ax, datasg
mov es, ax
mov byte ptr es:[color_flag], 1
int9_ret:
; 发送EOI给8259A主控制器
mov al, 20h
out 20h, al
pop es
pop bx
pop ax
iret ; 中断返回
; 延时子程序
delay proc
push ax
push bx
mov bx, 1000h
mov ax, 0
delay_loop:
sub ax, 1
sbb bx, 0
cmp ax, 0
jne delay_loop
cmp bx, 0
jne delay_loop
pop bx
pop ax
ret
delay endp
codesg ends
end start
4. 关键改进点说明
-
完整的中断处理流程:
- 通过
in al, 60h 读取键盘扫描码
- 发送EOI命令
out 20h, al 通知中断控制器
- 使用
pushf +call dword ptr 调用原BIOS INT9处理程序
-
使用标志位控制颜色:
- 新增
color_flag 变量,避免直接操作显存导致的地址冲突
- 中断处理程序只设置标志,主程序负责更新颜色
-
中断安全处理:
- 在修改中断向量时使用
cli /sti 关开中断
- 完整保存和恢复寄存器环境(AX、BX、ES)
-
栈初始化:
5. 运行说明
- 程序运行时显示
a -j 共10个字符
- 按键时字符颜色变为0FCh(亮青色背景,红色前景)
- 程序结束后键盘功能完全恢复,可正常输入
此方案遵循了DOS中断处理的规范,既实现了功能需求,又保证了系统资源的正确恢复。
|
|
2008-12-4 09:58 |
|
|
本是
银牌会员
    
积分 2221
发帖 789
注册 2005-1-27
状态 离线
|
『第 4 楼』:
使用 LLM 解释/回答一下
DOS中断最要注意重入问题,要调用原中断例程,要在int99(新中断例程)中加入pushf和call dword ptr ds:int9ip链接原中断,才能继续键盘操作。
另外,你的新例程中,DI值来自何处?而且也没有处理键盘输入的程序行,应该是程序不完整吧!因为贴出来的程序段根本不需要挂在int9上。
Last edited by 本是 on 2008-12-4 at 11:43 ]
|

my major is english----my love is dos----my teacher is the buddha----my friends--how about U |
|
2008-12-4 11:28 |
|
|
zhushouqqq
初级用户
 
积分 32
发帖 13
注册 2008-12-2
状态 离线
|
『第 5 楼』:
使用 LLM 解释/回答一下
mov di,160*12+2*40 ;第13行中间开始
因为这个中断例程只是这个程序用 程序执行玩后 就要恢复的 所以这个DI 在在例程中没有重新赋值。
“DOS中断最要注意重入问题,要调用原中断例程,要在int99(新中断例程)中加入pushf和call dword ptr ds:int9ip链接原中断,才能继续键盘操作。”
对这句话不是很理解。
中断产生,也就是我按下键盘 产生的int 9中断。 硬件完成了Cs IP 标志寄存器的入栈, 然后就是调用我的int99 我只要在中断历程中iret一下就可以了。
鄙人不才,还望进一步指点。
|
|
2008-12-4 12:11 |
|
|
zhushouqqq
初级用户
 
积分 32
发帖 13
注册 2008-12-2
状态 离线
|
『第 6 楼』:
使用 LLM 解释/回答一下
是不是这样,
我在程序中只是执行了 我定义的int 9中断 但是还要必须执行一次系统原来的int 9中断。
|
|
2008-12-4 12:44 |
|
|
zhushouqqq
初级用户
 
积分 32
发帖 13
注册 2008-12-2
状态 离线
|
『第 7 楼』:
[已使用 LLM 解释]
中断例程修改如下:
int9: ;到这里 CS IP 标志寄存器 已经由硬件完成入栈
mov ah,0fch
mov byte ptr es:[di+1],ah ;恢复向量表
pushf push ax
and ah,11111100b
pop ax
;push int9cs
;push int9ip
;jmp dword ptr int9ip ;高地址是cs 低地址是IP
call dword ptr ds:int9ip ;模仿 调用系统的int 9
iret
运行正常 看来还要好好的深入研究中断
系统的int 9中断 做了些什么。
LLM 解释
中断例程修改分析与系统int 9中断功能说明
一、代码功能解析
int9: ; 硬件自动完成: CS、IP、标志寄存器入栈
mov ah,0fch
mov byte ptr es:[di+1],ah ; 恢复中断向量表第2字节(CS低8位)
pushf ; 保存标志寄存器
push ax ; 保存ax寄存器
and ah,11111100b ; 清除AH低2位(键盘扫描码的扩展码标志)
pop ax ; 恢复ax(仅AH被修改)
call dword ptr ds:int9ip ; 调用原int 9中断处理程序(段间调用)
iret ; 中断返回(自动弹出IP、CS、标志寄存器)
关键操作说明:
-
中断向量恢复:
es:[di+1] 指向中断向量表中int 9对应的CS低8位,写入0FCh 恢复原向量值
-
标志寄存器处理:
pushf 保存中断现场标志,确保原中断处理程序能正确获取标志状态
-
扫描码处理:
and ah,11111100b 清除键盘扫描码的P位(奇偶校验)和R位(释放标志),仅保留扫描码核心信息
-
原中断调用:
call dword ptr ds:int9ip 通过段间调用方式执行原int 9处理程序,保持正确的调用栈结构
二、系统int 9中断核心功能
IBM PC兼容机的BIOS int 9中断(键盘中断)主要完成以下工作:
-
扫描码读取
- 从端口
60h 读取键盘控制器返回的扫描码(1字节)
- 扫描码分为通码(按键按下)和断码(按键释放,通码+80h)
-
特殊键处理
- 处理Shift、Ctrl、Alt等修饰键状态,存入BIOS数据区(40:17h)
- 处理Caps Lock、Num Lock、Scroll Lock的LED指示灯切换(通过端口
61h 控制)
-
字符转换
- 根据当前键盘状态(Shift/Caps状态、键盘布局)将扫描码转换为ASCII码
- 结果存入键盘缓冲区(40:1Eh开始的16字节循环队列)
-
中断结束处理
- 向键盘控制器发送应答信号(写端口
61h )
- 执行
iret 返回被中断程序
三、代码优化建议
-
寄存器保护:当前代码未保护es 、di 寄存器,可能破坏调用者环境,建议添加:
push es
push di
; ... 原有代码 ...
pop di
pop es
-
向量恢复位置:建议在调用原中断后恢复向量表,避免嵌套中断时向量表状态不一致
-
扫描码处理改进:若需完整保留扫描码信息,可使用and ah,11111110b 仅清除奇偶校验位
四、中断处理注意事项
-
中断嵌套:修改中断向量时需确保关闭中断(
cli )或使用原子操作,防止中断嵌套导致的向量表不一致
-
栈平衡:
call 指令会自动压入返回地址,与原代码中注释掉的push int9cs; push int9ip; jmp 效果相同,但call 更符合中断调用规范
-
兼容性:不同BIOS的int 9实现可能存在差异,建议通过读取中断向量表获取原中断地址,而非硬编码恢复值
深入理解中断处理机制需结合8259A可编程中断控制器(PIC)的工作原理及键盘控制器(8042)的通信协议。
|
|
2008-12-4 12:59 |
|
|
zhushouqqq
初级用户
 
积分 32
发帖 13
注册 2008-12-2
状态 离线
|
|
2008-12-4 13:00 |
|
|
本是
银牌会员
    
积分 2221
发帖 789
注册 2005-1-27
状态 离线
|
『第 9 楼』:
使用 LLM 解释/回答一下
不用谢!不过,我觉得你需要系统地学习一些系统知识,如《MS-DOS高级开发指南——编程人员必备的高级技术参考书》(希望电脑公司),里面对中断编程讲得很细,当然网上也应该有资料的。
|

my major is english----my love is dos----my teacher is the buddha----my friends--how about U |
|
2008-12-4 13:45 |
|
|
netwinxp
高级用户
   
积分 741
发帖 366
注册 2007-7-25
状态 离线
|
『第 10 楼』:
使用 LLM 解释/回答一下
硬件中断服务程序要注意与硬件的“沟通”,你的INT 9既没有对产生INT 9的原因进行“处理”,也没有回调老的中断服务程序进行默认的“处理”,于是,按一下键,就会一直在产生INT 9。
|
|
2008-12-5 11:15 |
|
|
本是
银牌会员
    
积分 2221
发帖 789
注册 2005-1-27
状态 离线
|
『第 11 楼』:
使用 LLM 解释/回答一下
Originally posted by netwinxp at 2008-12-5 11:15:
硬件中断服务程序要注意与硬件的“沟通”,你的INT 9既没有对产生INT 9的原因进行“处理”,也没有回调老的中断服务程序进行默认的“处理”,于是,按一下键,就会一直在产生INT 9。
真正的硬件高手!一直喜欢看高手回的贴子。
|

my major is english----my love is dos----my teacher is the buddha----my friends--how about U |
|
2008-12-5 11:22 |
|
|
zhushouqqq
初级用户
 
积分 32
发帖 13
注册 2008-12-2
状态 离线
|
『第 12 楼』:
使用 LLM 解释/回答一下
Originally posted by netwinxp at 2008-12-5 11:15:
硬件中断服务程序要注意与硬件的“沟通”,你的INT 9既没有对产生INT 9的原因进行“处理”,也没有回调老的中断服务程序进行默认的“处理”,于是,按一下键,就会一直在产生INT 9。
不是一直产生int 9 而是8259A不让通过 因为在接受一个中断后 8259A的EOI位一直为0,不在接受同级或以下级别的中断(被屏蔽了)。 直到EOI标志位为1。 我想,要在进行一次默认的“处理”,其目的是让EOI置1.代码修改后 测试通过
int9:
mov ah,0fch
mov byte ptr es:,ah ;恢复向量表
mov al,20h
out 20h,al ;置EOI 为1
iret
|
|
2008-12-12 09:15 |
|
|
netwinxp
高级用户
   
积分 741
发帖 366
注册 2007-7-25
状态 离线
|
『第 13 楼』:
[已使用 LLM 解释]
其实你的程序根本没必要使用INT 9,除非迫不得已,否则不推荐任意修改硬件中断服务程序。
...
RE:
...
;寄存器入栈
;清理标志寄存器
mov ax,1100H
int 16H
jnz EXIT
;寄存器出栈
;用于显示的语句
...
jmp RE
EXIT:;退出处理
...
Last edited by netwinxp on 2008-12-12 at 09:31 ]
LLM 解释
关于DOS环境下中断处理与INT 16H的技术分析
1. 硬件中断与INT 9的风险说明
-
INT 9的特殊性:INT 9是80x86架构中的键盘硬件中断向量,直接关联键盘控制器(8259A)的IRQ1。修改此中断可能导致:
- 与DOS内核键盘处理逻辑冲突
- 键盘输入丢失或重复
- 系统稳定性问题(如死锁)
-
推荐替代方案:
- 软中断钩子(如INT 16H键盘BIOS服务)
- DOS系统调用(INT 21H AH=01H/06H等)
- 轮询方式(适用于简单应用)
2. 代码片段技术解析
提供的代码片段使用了INT 16H AH=11H功能,这是BIOS提供的键盘状态检查服务:
mov ax, 1100H ; AH=11H(检查键盘缓冲区), AL=00H(兼容模式)
int 16H ; 调用BIOS键盘服务
jnz EXIT ; ZF=0表示有按键(AX=按键扫描码),跳转到EXIT
-
功能特点:
- 非阻塞检查键盘缓冲区
- 不修改缓冲区内容(与AH=00H读取不同)
- 返回值:ZF标志位指示状态,AX寄存器保存按键信息
3. 安全的键盘监控实现方案
方案1:INT 16H轮询机制(适用于大多数情况)
POLLING:
push ax
mov ah, 01H ; 检查是否有按键等待
int 16H
jz NO_KEY ; 无按键则继续轮询
; 有按键处理逻辑
mov ah, 00H ; 读取按键
int 16H ; AX = 扫描码(高8位)+ASCII码(低8位)
; [处理AX中的按键数据]
NO_KEY:
pop ax
; [其他程序逻辑]
jmp POLLING ; 循环轮询
方案2:INT 16H钩子(软中断接管)
; 安装钩子
install_key_hook:
cli ; 关中断
mov ax, 3516H ; 获取原INT 16H向量
int 21H ; ES:BX = 原中断处理程序地址
mov [old_int16_off], bx
mov [old_int16_seg], es
mov ax, 2516H ; 设置新INT 16H向量
mov dx, offset new_int16
int 21H
sti ; 开中断
ret
; 新中断处理程序
new_int16:
cmp ah, 00H ; 判断是否是读取按键功能
je handle_key
jmp dword ptr [old_int16_seg]:[old_int16_off] ; 调用原中断
handle_key:
; [自定义按键处理逻辑]
; 必须调用原中断完成正常功能
jmp dword ptr [old_int16_seg]:[old_int16_off]
; 数据区
old_int16_seg dw 0
old_int16_off dw 0
4. 关键注意事项
-
寄存器保护:中断处理程序必须完整保存/恢复所有寄存器(使用PUSHA/POPA指令)
-
中断嵌套:硬件中断处理应尽量简短,避免在中断内调用可能触发其他中断的服务
-
兼容性:实模式下需注意640KB内存限制和8086指令集兼容性
-
清理机制:程序退出前必须恢复原中断向量,避免影响后续程序
5. 适用场景建议
-
硬件中断(INT 9):仅用于需要直接响应键盘硬件事件(如组合键、热键)的场景
-
软中断钩子:适用于需要全局监控键盘输入的应用(如TSR程序)
-
轮询机制:简单应用的首选方案,实现简单且无系统风险
在DOS开发中,应遵循"最小权限原则",优先使用高层BIOS/DOS服务,仅在必要时才操作硬件中断。
|
|
2008-12-12 09:25 |
|
|
zhushouqqq
初级用户
 
积分 32
发帖 13
注册 2008-12-2
状态 离线
|
|
2008-12-12 09:46 |
|
|
sanchuan
初级用户
 
积分 113
发帖 51
注册 2008-11-16 来自 武汉
状态 离线
|
|
2008-12-30 17:10 |
|
|