MS-DOS中断处理深入解析
1. IRQ分配与INT 9 BIOS例程
在计算机系统中,IRQ(中断请求)分配对于硬件设备的正常工作至关重要。以下是ISA总线的IRQ分配表:
| IRQ编号 | 中断号 | 描述 |
| ---- | ---- | ---- |
| 0 | 8 | 系统定时器(每秒18.2次) |
| 1 | 9 | 键盘 |
| 2 | 0Ah | 可编程中断控制器 |
| 3 | 0Bh | COM2(串行端口2) |
| 4 | 0Ch | COM1(串行端口1) |
| 5 | 0Dh | LPT2(并行端口2) |
| 6 | 0Eh | 软盘控制器 |
| 7 | 0Fh | LPT1(并行端口1) |
| 8 | 70h | CMOS实时时钟 |
| 9 | 71h | (重定向到INT 0Ah) |
| 10 | 72h | (可用)声卡 |
| 11 | 73h | (可用)SCSI卡 |
| 12 | 74h | PS/2鼠标 |
| 13 | 75h | 数学协处理器 |
| 14 | 76h | 硬盘控制器 |
| 15 | 77h | (可用) |
当键盘产生中断时,BIOS会执行INT 9例程,其执行步骤如下:
1. 重新启用硬件中断,以确保系统定时器不受影响。
2. 从键盘端口输入扫描码,尝试将其转换为ASCII字符,若无法转换则将ASCII码设为零。然后将扫描码和ASCII码存储在BIOS数据区的32字节循环键盘缓冲区中。
3. 执行IRET(中断返回)指令,从堆栈中弹出IP、CS和标志寄存器,将控制权返回给中断发生时正在执行的程序。
2. 中断控制指令
CPU有一个名为中断标志(IF)的标志位,用于控制CPU对外部(硬件)中断的响应方式。当IF = 1时,中断启用;当IF = 0时,中断禁用。
2.1 STI指令
STI指令用于启用外部中断。例如,当系统响应键盘输入时,会暂停当前程序,调用INT 9将按键存储在缓冲区,然后返回当前程序。通常情况下,中断标志是启用的,否则系统定时器将无法正确计算时间和日期,输入的按键也会丢失。
2.2 CLI指令
CLI指令用于禁用外部中断。该指令应谨慎使用,仅在执行关键操作且不能被中断时使用。例如,在更改SS和SP寄存器的值时,如果代码被中断,可能会导致SS寄存器指向新的堆栈段,而堆栈指针尚未更新。为了安全起见,应使用CLI清除中断标志来禁用中断,使用STI启用中断:
cli ; 禁用中断
mov ax,mystack ; 重置SS
mov ss,ax
mov sp,100h ; 重置SP
sti ; 重新启用中断
需要注意的是,中断禁用时间不应超过几毫秒,否则可能会丢失按键并减慢系统定时器的速度。当CPU响应中断处理程序时,其他中断会立即被禁用,而MS - DOS和BIOS中断服务例程在开始执行时会重新启用中断。
3. 编写自定义中断处理程序
中断向量表的存在使得IBM - PC的设计者能够在不更换ROM芯片的情况下对BIOS例程进行修改和更正。中断向量表中的每个地址都指向一个称为中断处理程序或中断服务例程(TSR)的过程。应用程序可以用新的地址替换表中的地址,从而指向新的中断处理程序。
3.1 获取和设置中断向量
INT 21h的功能25h和35h可用于安装中断处理程序。
- 功能35h(获取中断向量):返回中断向量的段 - 偏移地址。通过将所需的中断号放入AL寄存器,调用该功能,MS - DOS会在ES:BX中返回32位向量。例如,获取INT 9向量的代码如下:
.data
int9Save LABEL WORD
DWORD 7 ; 存储旧的INT 9地址
.code
mov ah,35h ; 获取中断向量
mov al,9 ; 针对INT 9
int 21h ; 调用MS - DOS
mov int9Save,BX ; 存储偏移量
mov int9Save + 2,ES ; 存储段地址
- 功能25h(设置中断向量):允许用新的处理程序替换现有的中断处理程序。将中断号放入AL寄存器,将自己的中断处理程序的段 - 偏移地址放入DS:DX寄存器,然后调用该功能。例如,设置INT 9中断向量的代码如下:
mov ax,SEG kybd_rtn ; 键盘处理程序
mov ds,ax ; 段地址
mov dx,OFFSET kybd_rtn ; 偏移地址
mov ah,25h ; 设置中断向量
mov al,9h ; 针对INT 9h
int 21h
3.2 Ctrl - Break处理程序示例
当用户在MS - DOS程序等待输入时按下Ctrl - Break,控制权会传递给默认的INT 23h中断处理程序,该处理程序会终止当前运行的程序,这可能会使程序处于不稳定状态。可以通过替换INT 23h处理程序中的代码来防止程序停止。以下是一个安装简单Ctrl - Break处理程序的示例:
TITLE Control - Break Handler (Ctrlbrk.asm)
; 此程序安装自己的Ctrl - Break处理程序,防止用户使用Ctrl - Break(或Ctrl - C)停止程序
; 程序输入并回显按键,直到按下Esc键
INCLUDE Irvine16.inc
.data
breakMsg BYTE "BREAK",0
msg BYTE "Ctrl - Break demonstration.",0Dh,0Ah
BYTE "This program disables Ctrl - Break (Ctrl - C). Press any",0Dh,0Ah
BYTE "keys to continue, or press ESC to end the program.",0Dh,0Ah,0
.code
main PROC
mov ax,data
mov ds,ax
mov dx,OFFSET msg ; 显示问候消息
call WriteString
install_handler:
push ds ; 保存DS
mov ax,@code ; 初始化DS为代码段
mov ds,ax
mov ah,25h ; 设置中断向量
mov al,23h ; 针对中断23h
mov dx,OFFSET break_handler
int 21h
pop ds ; 恢复DS
L1:
mov ah,1 ; 等待按键,回显
int 21h
cmp al,1Bh ; ESC按下?
jnz L1 ; 否:继续
exit
main ENDP
break_handler PROC
push ax
push dx
mov dx,OFFSET breakMsg
call WriteString
pop dx
pop ax
iret
break_handler ENDP
END main
在上述代码中,main过程初始化INT 23h的中断向量,所需的输入参数为:
- AH = 25h
- AL = 要处理的中断向量(23h)
- DS:DX = 新的Ctrl - Break处理程序的段/偏移地址
程序的主循环会持续输入并回显按键,直到按下Esc键。当按下Ctrl - Break时,break_handler过程会执行,显示消息并立即返回调用程序。
4. 终止并驻留程序(TSR)
终止并驻留程序(TSR)会安装在内存中,直到被特殊的移除实用软件移除或计算机重新启动。TSR在被某些事件(如按键)激活之前处于休眠状态。
4.1 早期TSR的兼容性问题
在早期,当多个程序替换相同的中断向量时,会出现兼容性问题。旧程序会使向量指向自己的程序,而不提供对使用相同向量的其他程序的前向链。后来,为了解决这个问题,TSR作者会保存要替换的中断的现有向量,并在自己的过程处理完中断后前向链到原始中断处理程序。但这意味着最后安装的TSR在处理中断时具有最高优先级,用户有时需要小心按照特定顺序加载TSR程序。当MS - DOS应用程序广泛使用时,出现了商业编程工具来管理多个内存驻留程序。
4.2 键盘示例
假设我们编写一个中断服务例程,用于检查键盘输入的每个字符并将其存储在位置10B2:0020。安装TSR的步骤如下:
1. 从中断向量表中获取当前的INT 9向量并保存。
2. 用我们的ISR地址替换表中的条目。
当按下键盘按键时,键盘控制器会将单个字节传输到计算机的键盘端口,触发硬件中断。8259 PIC将中断号传递给CPU,CPU会跳转到中断向量表中的INT 9地址,即我们的ISR地址。我们的程序可以检查键盘字节,处理完后跳转到原始的BIOS键盘处理程序。这个过程的流程图如下:
graph LR
A[键盘按键按下] --> B[触发硬件中断]
B --> C[8259 PIC传递中断号]
C --> D[CPU跳转到INT 9地址(我们的ISR)]
D --> E[检查键盘字节]
E --> F[跳转到原始BIOS键盘处理程序]
F --> G[处理完返回原程序]
5. 应用:No_Reset程序
No_Reset程序是一种简单的内存驻留程序,用于防止系统通过Ctrl - Alt - Delete键重启。安装该程序后,系统只能通过按下Ctrl - Alt - RightShift - Del组合键重启,或者关闭并重新启动计算机来停用该程序。需要注意的是,该程序仅在以MS - DOS模式启动计算机时有效,Microsoft Windows NT、2000和XP会阻止TSR程序拦截键盘按键。
5.1 MS - DOS键盘状态字节
在开始编写程序之前,需要了解MS - DOS在低内存中保存的键盘状态字节的位置。键盘状态标志存储在RAM的0040:0017h位置,每个位的含义如下:
| 位位置 | 含义(值为1时) |
| ---- | ---- |
| 7 | 插入模式开启 |
| 6 | 大写锁定开启 |
| 5 | 数字锁定开启 |
| 4 | 滚动锁定开启 |
| 3 | ALT键按下 |
| 2 | CTRL键按下 |
| 1 | 左Shift键按下 |
| 0 | 右Shift键按下 |
此外,位于0040:0018h的另一个键盘状态字节重复了上述标志,除了位3显示Ctrl - NumLock当前是否激活。
5.2 安装程序
程序的安装代码位于末尾,因为它不会驻留在内存中。驻留部分从标签int9_handler开始,由INT 9h向量指向。以下是程序的主要部分:
TITLE Reset - Disabling program (No_Reset.asm)
; 此程序通过拦截INT 9键盘硬件中断,禁用通常的DOS重置命令(Ctrl - Alt - Del)
; 检查MS - DOS键盘标志中的移位状态位,将任何Ctrl - Alt - Del更改为Alt - Del
; 计算机只能通过输入Ctrl + Alt + Right shift + Del重启
.model tiny
.386
Right_shift EQU 01h
ctrl_key EQU 04h
alt_key EQU 08h
del_key EQU 53h
kybd_port EQU 60h
ORG 100h
start:
jmp setup ; 跳转到TSR安装
int9_handler PROC FAR
sti ; 启用硬件中断
pushf ; 保存寄存器和标志
push es
push ax
push di
mov ax,40h ; DOS数据段位于40h
mov es,ax
mov di,17h ; 键盘标志位置
mov ah,es:[di] ; 复制键盘标志到AH
L2:
test ah,ctrl_key ; CTRL键按下?
jz L5 ; 否:退出
test ah,alt_key ; ALT键按下?
jz L5 ; 否:退出
L3:
in al,kybd_port ; 读取键盘端口
cmp al,del_key ; DEL键按下?
jne L1 ; 否:退出
test ah,rt_shift ; 右Shift键按下?
jnz L1 ; 是:允许系统重置
L4:
and ah,NOT ctrl_key ; 否:关闭CTRL位
mov es:[di],ah ; 存储键盘标志
L1:
pop di ; 恢复寄存器和标志
pop ax
pop es
popf
jmp cs:[old_interrupt9] ; 跳转到INT 9例程
old_interrupt9 DWORD ?
int9_handler ENDP
end_TSR LABEL BYTE ; TSR程序结束
setup:
mov ax,3509h ; 获取INT 9向量
int 21h
mov word ptr old_interrupt9,bx ; 保存INT 9向量
mov word ptr old_interrupt9 + 2,es
mov ax,2509h ; 设置INT 9向量
mov dx,offset int9_handler
int 21h
mov ax,3100h ; 终止并驻留
mov dx,OFFSET end_TSR ; 指向驻留代码末尾
shr dx,4 ; 除以16
inc dx ; 向上舍入到下一个段落
int 21h
END start
安装程序的步骤如下:
1. 在setup标签处,调用INT 21h的功能35h获取当前的INT 9h向量,并将其存储在old_interrupt9中,以便程序能够前向链到现有的键盘处理程序。
2. 调用INT 21h的功能25h将中断向量9h设置为程序驻留部分的地址。
3. 调用INT 21h的功能31h退出到MS - DOS,将驻留程序留在内存中。
驻留程序的int9_handler过程会在每次按下键盘按键时执行。它会检查键盘标志字节,判断是否按下了Ctrl、Alt和Del键,以及右Shift键是否按下。如果按下了Ctrl - Alt - Del但没有按下右Shift键,会清除键盘标志字节中的Ctrl键位,从而禁用用户重启计算机的尝试。最后,程序会跳转到现有的BIOS INT 9h例程,以处理所有正常的按键输入。
通过以上内容,我们深入了解了MS - DOS中的中断处理机制,包括IRQ分配、中断控制指令、自定义中断处理程序的编写、终止并驻留程序的实现以及相关应用程序的开发。这些知识对于理解计算机系统的底层工作原理和进行系统编程具有重要意义。
MS-DOS中断处理深入解析
6. 中断处理相关问题解答
为了帮助大家更好地理解中断处理的相关内容,下面对一些常见问题进行解答。
| 问题 | 解答 |
|---|---|
| 1. 关键错误处理程序执行的默认操作是什么? | 文档未提及相关内容。 |
| 2. 中断向量表的每个条目包含什么? | 每个条目指向一个称为中断处理程序或中断服务例程(TSR)的过程。 |
| 3. INT 10h的中断向量存储在哪个地址? | 文档未提及相关内容。 |
| 4. 哪个控制器芯片生成硬件中断? | 8259 PIC生成硬件中断。 |
| 5. 哪个指令禁用硬件中断? | CLI指令禁用硬件中断。 |
| 6. 哪个指令启用硬件中断? | STI指令启用硬件中断。 |
| 7. 哪个IRQ级别优先级最高,0还是15? | IRQ 0级别优先级最高。 |
| 8. 根据对IRQ级别的了解,如果一个程序正在创建磁盘文件,此时按下键盘上的键,你认为按键何时会被放入键盘缓冲区——在文件创建之前还是之后? | 由于系统定时器(IRQ 0)和键盘(IRQ 1)的中断优先级较高,当按下键盘按键时,会触发键盘中断,此时会暂停当前创建磁盘文件的程序,将按键放入键盘缓冲区,然后再返回继续创建磁盘文件,所以按键会在文件创建过程中被放入键盘缓冲区。 |
| 9. 当按下键盘上的键时,执行哪个硬件中断? | 当按下键盘上的键时,执行INT 9硬件中断。 |
| 10. 当中断处理程序完成时,CPU如何恢复到中断触发前的执行位置? | 执行IRET(中断返回)指令,从堆栈中弹出IP、CS和标志寄存器,将控制权返回给中断发生时正在执行的程序。 |
7. 中断处理的实际应用场景分析
中断处理在计算机系统中有着广泛的应用场景,下面对一些实际应用场景进行分析。
7.1 实时数据采集
在实时数据采集系统中,传感器会不断地产生数据。通过设置相应的中断处理程序,可以在传感器数据准备好时立即触发中断,CPU暂停当前任务,读取传感器数据并进行处理。例如,在工业自动化生产线上,温度传感器、压力传感器等会实时采集数据,当数据更新时,触发中断,CPU及时处理这些数据,确保生产过程的稳定和安全。
graph LR
A[传感器数据准备好] --> B[触发硬件中断]
B --> C[CPU跳转到中断处理程序]
C --> D[读取传感器数据]
D --> E[处理数据]
E --> F[返回原程序]
7.2 多任务处理
在多任务操作系统中,中断处理可以实现任务的切换。当一个任务执行一段时间后,系统定时器会触发中断,CPU将当前任务的上下文保存到堆栈中,然后切换到另一个任务继续执行。这样可以实现多个任务的并发执行,提高系统的效率。
graph LR
A[系统定时器触发中断] --> B[CPU保存当前任务上下文]
B --> C[选择下一个任务]
C --> D[加载下一个任务上下文]
D --> E[执行下一个任务]
E --> F[再次触发中断时重复上述过程]
8. 中断处理的优化建议
在实际应用中,为了提高中断处理的效率和稳定性,可以采取以下优化建议。
8.1 减少中断处理时间
中断处理程序应尽量简洁,避免执行复杂的操作。如果需要进行复杂的处理,可以将部分任务放到中断处理程序之外,通过设置标志位或队列的方式,在主程序中进行处理。例如,在处理键盘输入时,中断处理程序只负责将按键数据放入缓冲区,而对按键数据的解析和处理可以在主程序中进行。
8.2 合理分配IRQ资源
不同的硬件设备具有不同的IRQ级别,应根据设备的重要性和使用频率合理分配IRQ资源。例如,系统定时器和键盘等重要设备应分配较高优先级的IRQ,以确保其能够及时响应。
8.3 避免中断嵌套过深
中断嵌套过深会增加系统的复杂度和开销,可能导致系统不稳定。在编写中断处理程序时,应尽量避免在中断处理程序中再次触发中断。如果确实需要嵌套中断,应确保嵌套层次不要过深。
9. 总结
MS - DOS中的中断处理机制是计算机系统底层的重要组成部分,它为系统的高效运行和硬件设备的正常工作提供了保障。通过本文的介绍,我们了解了IRQ分配、中断控制指令、自定义中断处理程序的编写、终止并驻留程序的实现以及相关应用程序的开发。
在实际应用中,我们可以根据具体需求,灵活运用这些知识,开发出高效、稳定的系统程序。同时,我们也应该注意中断处理过程中的一些问题,如中断处理时间的控制、IRQ资源的分配和中断嵌套的深度等,以确保系统的性能和稳定性。
希望本文能够帮助大家更好地理解和掌握MS - DOS中断处理的相关知识,为进一步的学习和实践打下坚实的基础。
超级会员免费看
55

被折叠的 条评论
为什么被折叠?



