Skip to content

第11讲:中断

本周核心:理解软中断和硬中断的区别,掌握 int/iret 的执行机制,理解中断向量表的结构。


一、中断的分类

1.1 软中断(Software Interrupt)

由程序员通过 int n 指令主动触发。int 21h 指令本身在内存中占用 2 字节(机器码 CD 21)。存在于内存中的中断称为软中断。

1.2 硬中断(Hardware Interrupt)

由外部硬件事件触发,不由程序员写 int 指令,指令本身也不存在于内存中。例如:

  • int 8h:定时器中断,每约 1/18 秒自动触发一次
  • int 9h:键盘中断,用户按下/释放按键时自动触发
asm
mov ax, 0            ; 假设这两条指令执行了 1/18 秒
; CPU在此处接收并执行了 int 8h 指令(定时器),但 int 8h 不在代码中
mov bx, 1
again:
add ax, bx
; 用户按了某个键
; CPU在此处接收并执行了 int 9h 指令(键盘),同样 int 9h 也不在代码中
cmp ax, 100
jb again

硬中断是异步的:CPU 在执行完当前指令后检查是否有硬件中断请求,有则响应后继续执行。


二、int 指令的执行过程

int 21h 为例,CPU 执行此指令时做以下操作:

① pushf                    ; 把标志寄存器 FL 压入堆栈(也可写成 push fl)
② push cs                  ; 把当前代码段段地址压入堆栈
③ push offset back         ; 把返回偏移地址压入堆栈
④ jmp dword ptr 0:[84h]   ; 跳转到中断处理程序
                           ; int n 的目标地址总是存放在 dword ptr 0:[n*4] 处
                           ; dword ptr 0:[n*4] 称为 int n 的中断向量

完整的例子:

asm
mov ah, 2
mov dl, 'A'
int 21h            ; CPU在执行int 21h指令时做以下操作:
                   ;   ① pushf
                   ;   ② push cs
                   ;   ③ push offset back
                   ;   ④ jmp dword ptr 0:[84h]
                   ; int n的目标地址总是存放在dword ptr 0:[n*4]处,
                   ; dword ptr 0:[n*4]称为int n的中断向量
back:
mov ah, 4Ch
mov al, 0
int 21h

中断处理程序的入口地址约定

word ptr 0:[n*4]     = 中断处理程序的偏移地址
word ptr 0:[n*4+2]   = 中断处理程序的段地址

例如 int 21h:
  word ptr 0:[84h]   = offset int_21h(int 21h 处理程序的偏移地址)
  word ptr 0:[86h]   = seg int_21h(int 21h 处理程序的段地址)

伪代码表示的中断处理程序:

asm
int_21h:             ; offset int_21h 已被保存到 word ptr 0:[84h] 中
                     ; seg int_21h 已被保存到 word ptr 0:[86h] 中
...
iret                 ; ★ 中断返回指令 (interrupt return)
                     ; CPU 在执行 iret 时做以下操作:
                     ;   ① pop ip
                     ;   ② pop cs
                     ;   ③ popf

int / iret 的压栈弹栈对应关系

int n 压栈:    pushf → push cs → push ip  → jmp far ptr 0:[n*4]
iret 弹栈:     pop ip → pop cs → popf

顺序恰好是完全逆序(后进先出),多了标志寄存器 FL 的保存和恢复。


三、int 与 call far 的比较

call far ptr fint n
压栈内容cs + ipFL + cs + ip
返回指令retfiret
目标地址来源指令中的立即数中断向量表 0:[n*4]
会改变 IF 标志吗不会会(关中断)

四、中断向量表结构

中断向量表位于内存的最低 1024 字节0000:0000 ~ 0000:03FF):

地址          内容
0000:0000     int 0  偏移地址    (除法错误)
0000:0002     int 0  段地址
0000:0004     int 1  偏移地址    (单步调试)
0000:0006     int 1  段地址
0000:0008     int 2  偏移地址    (NMI 非屏蔽中断)
0000:000A     int 2  段地址
0000:000C     int 3  偏移地址    (断点)
0000:000E     int 3  段地址
...
0000:0020     int 8  偏移地址    (定时器,硬中断)
0000:0022     int 8  段地址
0000:0024     int 9  偏移地址    (键盘,硬中断)
0000:0026     int 9  段地址
...
0000:0040     int 10h 偏移地址   (BIOS 视频服务)
0000:0042     int 10h 段地址
...
0000:0084     int 21h 偏移地址   (DOS 功能调用)
0000:0086     int 21h 段地址
...
0000:03FC     int FFh 偏移地址
0000:03FE     int FFh 段地址

五、常用中断速查表

中断号用途类型
int 0除法错误CPU 自动触发
int 1单步调试调试器用
int 3断点(机器码 0CCh)调试器用
int 8定时器(约 18.2 Hz)硬中断
int 9键盘输入硬中断
int 10hBIOS 视频服务(切换显示模式等)软中断
int 21hDOS 功能调用(I/O、文件、退出等)软中断

六、本周易错点

  1. 混淆 int 和 call:int 多压一个 FL 标志寄存器
  2. 混淆 iret 和 retf:iret 多弹一个 FL
  3. 中断向量表地址算错:int n 的向量在 0:[n×4],低 16 位是偏移,高 16 位是段地址
  4. 以为代码中出现的 int 8h / int 9h 就是硬中断——硬中断不由程序员写 int 指令
  5. int 3 是单字节指令(0CCh),而其他 int n 都是两字节(CD n)