一、中断是什么?——“门铃和紧急电话”
比喻:
想象你正在家里专心做作业(CPU在执行主程序),突然门铃响了(中断),你必须停下手头的事,去开门(响应中断服务)。
或者你正在看电视,突然接到一个紧急电话(硬件中断),你得立刻放下遥控器去接电话。
总结:
- 中断就是让CPU暂时停下当前工作,去处理一件更紧急的事,处理完再回来继续原来的工作。
二、异常是什么?——“家里突然跳闸了”
比喻:
你在炒菜,突然家里跳闸了(除零错误、访问非法内存等异常),你必须马上停下来,去查原因(异常处理),修好后才能继续做饭。
总结:
- 异常是程序运行中遇到的“意外事故”,需要特殊处理。
三、中断的分类——“不同的门铃和电话”
-
硬件中断(外部中断)
- 比如键盘敲击、鼠标点击、定时器到点、硬盘读写完成。
- 比喻:门铃、电话、快递员敲门。
-
软件中断(内部中断)
- 程序主动发出的“请求”,比如
int 21h
调用DOS服务。 - 比喻:你自己按下家里的紧急按钮,叫家人帮忙。
- 程序主动发出的“请求”,比如
-
异常
- 程序运行中遇到的错误,如除零、溢出、无效操作码。
- 比喻:家里跳闸、水管爆了。
四、中断的处理流程——“门铃响了怎么办?”
- 门铃响了(中断发生)
- 你记下当前做的事(CPU保存现场:寄存器、标志位等)
- 去开门(跳转到中断服务程序ISR)
- 处理完来客(完成中断服务)
- 回到原来位置继续做事(恢复现场,继续执行主程序)
在汇编里,这通常表现为:
- 保存现场:
push
寄存器 - 处理中断:执行ISR
- 恢复现场:
pop
寄存器 - 返回:
iret
(中断返回指令)
五、软件中断的例子——“按下服务铃”
1. 调用操作系统服务(如DOS)
比喻:你按下服务铃,叫服务员帮你倒水。
汇编代码:
mov ah, 09h ; 功能号:显示字符串
mov dx, offset msg ; 字符串地址
int 21h ; 按下21h号服务铃
int 21h
:告诉DOS“我要服务”- DOS根据
ah
的值决定帮你做什么
2. 自定义中断服务——“家里装自己的门铃”
比喻:你家装了个特殊门铃,按下后家人会做特定的事。
汇编代码(伪代码):
mov ax, seg my_isr
mov ds, ax
mov word ptr [int_vector*4], offset my_isr ; 设置中断向量
...
int int_vector ; 触发自定义中断
my_isr
:你家人写的“开门流程”int_vector
:门铃编号
六、异常处理——“事故应急预案”
1. 除零异常
比喻:你用水壶烧水,结果水壶没水(除数为零),水壶报警(CPU触发异常)。
汇编代码:
mov ax, 10
mov bx, 0
div bx ; 除以0,CPU会触发异常(INT 0)
- CPU自动跳转到异常处理程序(如INT 0的ISR)
2. 溢出异常
比喻:你往杯子里倒水,倒满了还继续倒,水溢出来(溢出),家里报警器响。
汇编代码:
add al, 200
add al, 100
into ; 如果溢出标志OF=1,触发溢出异常(INT 4)
七、中断向量表——“门铃号码簿”
比喻:家里有一本门铃号码簿,每个门铃(中断号)都对应一个处理流程(ISR地址)。
- 中断号:门铃编号(如INT 21h、INT 0)
- 中断向量表:存放所有门铃对应的处理流程地址(0x0000~0x03FF)
八、保护现场与恢复现场——“记住你在做什么”
比喻:你开门前,先把手头的作业收好,回来后再拿出来继续写。
汇编代码(ISR结构):
my_isr proc
push ax
push bx
...
; 处理中断
...
pop bx
pop ax
iret ; 中断返回
my_isr endp
iret
:比ret
多恢复标志寄存器,确保回来后一切如初。
九、嵌套中断——“门铃响个不停”
比喻:你刚去开门,门铃又响了。你得记住每次开门前的状态,处理完一层再回来。
- ISR要能正确保存/恢复现场,防止“丢作业”。
十、现代异常处理——“智能家居报警系统”
- 现代CPU有更复杂的异常处理机制(如分页异常、保护性异常)。
- 操作系统会捕获这些异常,弹出蓝屏、错误提示,或者让你“安全退出”。
十一、口诀总结
- 门铃响,先记事,开完门,再回来。
- 事故来,先停工,查原因,修好再继续。
- 门铃号码要记牢,处理流程别乱套。
- 保存现场是关键,恢复如初才安全。
十二、生活化小结
- 中断:外部事件打断你,必须优先处理(门铃、电话、快递)。
- 异常:内部事故,必须应急处理(跳闸、爆管)。
- 中断服务程序:处理门铃/事故的详细流程。
- 中断向量表:门铃号码簿,查找对应流程。
- 保存/恢复现场:记住你在做什么,回来不出错。
十三、硬件中断的实际例子——“键盘敲击的故事”
1. 键盘中断(INT 9)——“门铃响了,快递到了”
场景:
你正在写作业,突然门铃响了(你按下了键盘上的某个键),家里专门有个人负责开门(键盘中断服务程序)。
流程:
- 你(CPU)停下手头的事(主程序)。
- 记下当前进度(保存现场)。
- 跑去开门(执行键盘ISR)。
- 处理快递(读取键盘扫描码,存到缓冲区)。
- 回来继续写作业(恢复现场,继续主程序)。
汇编伪代码(实际操作系统会更复杂):
keyboard_isr proc
push ax
in al, 60h ; 读取键盘扫描码
; 处理扫描码,比如存到缓冲区
mov al, 20h
out 20h, al ; 通知8259中断控制器“我处理完了”
pop ax
iret
keyboard_isr endp
in al, 60h
:从键盘端口读数据out 20h, al
:告诉中断控制器可以接收下一个中断了
2. 定时器中断(INT 8)——“闹钟响了”
场景:
你设了个闹钟,每隔一段时间响一次,提醒你休息或切换任务。
流程:
- 闹钟响(定时器中断),你暂停当前工作,去做定时任务(如更新时间、切换进程),做完再回来。
十四、异常处理的实际例子——“厨房事故应急演练”
1. 除零异常(INT 0)——“水壶没水报警”
场景:
你用水壶烧水,结果水壶没水,水壶自动报警(CPU自动触发INT 0)。
操作系统的应急处理:
- 弹出“除零错误”提示,终止程序,防止更大事故。
汇编模拟:
mov ax, 10
mov bx, 0
div bx ; 这里会自动触发INT 0
; 操作系统会接管,弹出错误
2. 无效操作码异常(INT 6)——“不会的菜谱”
场景:
你让家人做一道没人会做的菜(CPU遇到无效指令),家人只能报警(CPU触发INT 6)。
十五、嵌套中断——“门铃连环响”
场景:
你刚去开门,门铃又响了。你得一层层记住每次开门前的状态,处理完一层再回来。
汇编技巧:
- ISR要保存所有可能被用到的寄存器,防止“丢作业”。
- 有时需要临时禁止更高优先级的中断(用
cli
指令),处理完再允许(用sti
)。
十六、中断优先级——“谁的门铃最急?”
比喻:
快递员、外卖员、亲戚、警察……门铃响了,谁最先开门?
- 中断控制器(如8259)负责排队,优先级高的先处理。
十七、操作系统中的中断与异常——“大管家调度一切”
- 操作系统会统一管理所有中断和异常,分配给不同的“服务员”处理。
- 用户程序一般不能直接操作硬件中断(门铃),只能通过系统调用(软件中断)请求服务。
十八、调试中断与异常的实用技巧
1. 用调试器单步跟踪——“回放门铃录像”
- 观察中断发生时,CPU跳转到哪里,现场是否保存完整。
- 检查
iret
返回后,程序是否能正常继续。
2. 用断点和寄存器窗口——“随时查账”
- 在ISR入口和出口打断点,检查寄存器、栈、标志位。
3. 用栈窗口观察参数——“桌面监控”
- 检查ISR是否正确保存/恢复了所有需要的寄存器。
十九、常见“事故”与排查方法
1. ISR没保存现场——“作业丢了”
- 现象:中断返回后,主程序寄存器内容乱了,程序出错。
- 解决:ISR必须
push
/pop
所有用到的寄存器。
2. ISR没通知中断控制器——“门铃一直响”
- 现象:中断服务程序处理完后,系统卡死或中断无法再次响应。
- 解决:ISR结尾要
out 20h, 20h
通知8259“我处理完了”。
3. ISR没用iret
返回——“回不去原来的地方”
- 现象:中断返回后,程序崩溃。
- 解决:ISR必须用
iret
,不能用普通ret
。
二十、现代CPU的异常与中断——“智能家居的全自动报警系统”
- 现代CPU有几十种中断和异常类型,操作系统会分门别类处理。
- 比如:分页异常、保护性异常、系统调用、硬件故障等。
二十一、生活化口诀再升级
- 门铃响,先记事,开完门,再回来。
- 事故来,先停工,查原因,修好再继续。
- 门铃号码要记牢,处理流程别乱套。
- 保存现场是关键,恢复如初才安全。
- 优先级高先开门,嵌套处理要记清。
- 通知大管家,别让门铃一直响。
- 用
iret
回原地,别用ret
走错路。
二十二、总结
- 中断:外部事件打断你,必须优先处理(门铃、电话、快递)。
- 异常:内部事故,必须应急处理(跳闸、爆管)。
- 中断服务程序:处理门铃/事故的详细流程。
- 中断向量表:门铃号码簿,查找对应流程。
- 保存/恢复现场:记住你在做什么,回来不出错。
- 优先级与嵌套:谁先处理,怎么一层层回来。
- 操作系统统一调度:大管家分配任务,保证家里井井有条。