CPU异常主要分为三类:错误类异常,陷阱类异常和终止类异常
1 错误类异常 Fault
CPU遇到该类异常后,会先将CS和EIP(当前发生错误的指令,而不是下一条指令)压栈,然后跳到异常处理函数中,执行完成后恢复到原位置重新执行该指令,如果还有错误,还会再进。
例如内存缺页异常就是错误类异常,CPU遇到缺页异常时会跳转到异常处理,将缺少的内存页从物理内存中置换回来,再恢复重新执行内存访问指令。
2 陷阱类异常 Trap
CPU遇到该类异常后,会将CS和EIP压栈,这个EIP就是当前指令的下一条指令的地址,注意的是下一条指令可能不是相邻的指令,如果导致异常的是跳转类指令,下一条指令可能会很远。
我们经常使用的INT 3就是陷阱类异常。
3 终止类异常 Abort
该类异常用于报告严重的错误,比如硬件错误和系统表中包含非法值或不一致的状态等。大多数终止异常可能是由于堆栈操作不当造成的,例如压栈和出栈不匹配,操作系统会将此类异常当做程序错误来处理,终止导致此类异常的程序。
4 异常列表
向量号 | 助记符 | 类型 | 描述 | 来源 |
0 | #DE | 错误 | 除零错误 | DVI和IDIV指令 |
1 | #DB | 错误/陷阱 | 调试异常,用于软件调试 | 任何代码或数据引用 |
2 | 中断 | NMI中断 | 不可屏蔽的外部中断 | |
3 | #BP | 陷阱 | 断点 | INT 3指令 |
4 | #OF | 陷阱 | 溢出 | INTO指令 |
5 | #BR | 错误 | 数组越界 | BOUND指令 |
6 | #UD | 错误 | 无效指令(没有定义的指令) | UD2指令(奔腾Pro CPU引入此指令)或任何保留的指令 |
7 | #NM | 错误 | 数学协处理器不存在或不可用 | 浮点或WAIT/FWAIT指令 |
8 | #DF | 终止 | 双重错误(Double Fault) | 任何可能产生异常的指令、不可屏蔽中断或可屏蔽中断 |
9 | #MF | 错误 | 向协处理器传送操作数时检测到页错误(Page Fault)或段不存在,486及以后集成了协处理器,本错误就保留不用了 | 浮点指令 |
10 | #TS | 错误 | 无效TSS | 任务切换或访问TSS |
11 | #NP | 错误 | 段不存在 | 加载段寄存器或访问系统段 |
12 | #SS | 错误 | 栈段错误 | 栈操作或加载SS寄存器 |
13 | #GP | 错误 | 通用/一般保护异常,如果一个操作违反了保护模式下的规定,而且该情况不属于其他异常,CPU就是认为是该异常 | 任何内存引用或保护性检查 |
14 | #PF | 错误 | 页错误 | 任何内存引用 |
15 | 保留 | |||
16 | #MF | 错误 | 浮点错误 | 浮点或WAIT/FWAIT指令 |
17 | #AC | 错误 | 对齐检查 | 对内存中数据的引用(486CPU引入) |
18 | #MC | 终止 | 机器检查(Machine Check) | 错误代码和来源与型号有关(奔腾CPU引入) |
19 | #XF | 错误 | SIMD浮点异常 | SIMD浮点指令(奔腾III CPU引入) |
20~31 | 保留 | |||
32~255 | 用户自定义中断 | 中断 | 可屏蔽中断 | 来自INTR的外部中断或INT n指令 |