x86中断
中断分类
外部中断: 按照是否宕机分为可屏蔽中断和不可屏蔽中断
内部中断: 按照中断是否正常,分为软中断和异常
外部中断
外部中断来自某一个外部硬件设备,所以也称为硬件中断
软件中断
由指令主动发起的中断,
int 8bit立即数
,支持256种中断int3
,调试断点指令,调试器fork子进程,将断点处的指令备份,替换为0xcc(int3指令的机器码),然后保存子进程的寄存器和相关内存单元压栈保存,执行中断处理程序,使用调试器断点查看到的寄存器的值i就是从刚刚保存的栈中提取的,恢复执行调试的进程就是将0xcc恢复为子进程原来的指令,然后恢复子进程原来的上下文,iret指令退出到断点处,继续执行子进程into
.中断溢出指令,4号中断bound
,检查数组索引越界指令,5号中断ud2
,未定义指令,6号中断,表示指令无效,
除了int指令外,其它指令可以称为异常指令,既具备软中断的主动行为,又具备异常的错误结果
中断是否无视elags的IF bit条件:
- 只要是导致运行错误的中断类型都会无视IF位,NMI,异常
int n
的软中断实现系统调用也不能无视
异常的分类
- fault,故障,调用中断处理程序返回后依然返回到产生异常的指令处,重新执行一次指令
- trap,陷阱,如
int3
指令,执行中断处理程序后回到产生异常的下一条指令处开始执行 - Abort,中止,OS会将此进程杀掉
异常和中断号
Vector Number | 描述 | 产生原因 | Type | Error Code | |
---|---|---|---|---|---|
0 | #DE | Divide error(除法错误) | div and idiv i指令 | fault | n |
1 | #DB | Debug(调试) | Any code or data reference | fault/trap | n |
2 | / | NMI Interrupt | 不可屏蔽中断 | 中断 | n |
3 | #BP | Breakpoint(断点) | int3 指令 | trap | n |
4 | #OF | Overflow(溢出) | into指令 | trap | N |
5 | #BR | bound range exceeded(数组下表越界) | bound指令 | fault | n |
6 | #UD | invalid opcode(无效指令) | fault | n | |
7 | #NM | Device not available 设备不空闲 | 浮点或者wait指令 | fault | n |
8 | #DF | Double fault | 任何指令 | abort | y(0) |
9 | #MF | Coprocessor segment overrun | floating-point 指令 | fault | n |
10 | #TS | invalid Tss | 任务切换或者tss获取权限 | fault | y |
11 | #NP | segment not present | 加载段寄存器出错或获取系统段出错 | fault | y |
12 | #SS | stack segment fault | 栈操作或栈寄存器加载错误 | fault | y |
13 | #GP | general protection | 任何内存访问或其它的保护检查错误 | fault | y |
14 | #PF | page fault | 缺页异常 | fault | y |
15 | 保留位 | ||||
16 | #MF | floating-point error(math fault) | 浮点指令错误 | fault | N |
17 | #AC | alignment cheek | 任何数据引用错误 | fault | Y(0) |
18 | #MC | machine check | error codes (if any) and source are model dependent4 | abort | N |
19 | #XM | SIMD floation-point exception | 单指令多数据 | fault | N |
20-31 | 保留 | ||||
32-255 | Maskable interrupts | 来自INTR的外部中断或INT n指令 | interrupt |
中断的本质CPU收到中断信号,调用相应的中断处理程序,为了同一中断管理,把外部设备\内部指令的各种中断类型归为一种管理方式
异常和NMI不可屏蔽中断的向量号由CPU自动提供,而外部中断的可屏蔽中断号由中断控制器提供(8259A),
中断描述符表
中断发生后,eflags中的NT bit和TF bit都会被置0,
- 如果是中断门,则eflags的IF=0,目的是避免中断嵌套,执行中断时又产生了新的中断,同一种中断未处理完又来了一个,会导致GP异常
- 如果是陷阱门或任务门,IF不会清零,陷阱门允许CPU响应更高级别的中断,任务门当然要开中断,
从中断返回的指令是iret
,从栈中恢复cs,eip,eflags和依据特权级恢复ss,esp等.
修改IF位的原子指令, sti:开中断if=1,cli关中断=0,只有来自INTR的外部中断会被屏蔽,其它类型的中断无影响
eflags中的NT 和 TF位
TF表示
trap flag
,陷阱标志位,tf=1
开启,单步调试:每执行一次指令就产生中断,所以中断处理程序不允许单步执行NT(nest task flag)
,任务嵌套标志位,任务嵌套调用指的是cpu将当前执行的任务挂起,待执行完新任务,回到旧任务执行,为什么能回到旧任务?
- 新任务的tss有旧任务tss指针
NT=1
表示有别的任务调用了它
怎么回到旧任务?通过
iret
iret指令功能
- 中断返回
- 返回到调用自己执行的旧任务,通过
NT
位,iret能直到是执行中断返回还是回到旧任务
中断发生时的压栈
类似调用门返回,ss,esp,eflags,cs,eip,[error code]
有error code时,中断返回需要手动清理栈
error code
选择子指明中断发生在哪一个段上
31-16 | 15-3 | 3-2 | 2-1 | 1-0 |
---|---|---|---|---|
0 | 选择子高13bit索引 | TI | IDT | EXT |
external event
,外部事件:指明中断源是否来自处理器外部,=1表示中断源是NMI或外部设备,IDT
:=1表示指向IDT
,=0则TI
=1表示在LDT中,=0表示在GDT中
通常0~32内的异常能够压入error code,32-255和int 软中断不会产生error code.
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!