★PART1:中断和异常概述
1. 中断(Interrupt)
中断包括硬件中断和软中断。硬件中断是由外围设备发出的中断信号引发的,以请求处理器提供服务。当I/O接口发出中断请求的时候,会被像8259A和I/O APIC这样的中断寄存器手机,并发送给处理器。硬件中断完全是随机产生的,与处理器的执行并不同步。当中断发生的时候,处理器要先执行完当前的指令(指的是正在执行的指令),然后才能对中断进行处理。
软中断是由int n指令引发的中断处理器,n是中断号(类型码)。
2. 异常(Exception)
异常就是第9章略过的内部中断。内部中断是处理器内部产生的中断,表示在指令执行的时候遇到了错误。当处理器执行一条非法指令(引用一个不合标准的段,任务切换的时候TSS选择子不是有效的,访问了一个没有登记的页等等)。简单来说就是指令不能正常执行的时候,将引发这种类型的中断。
异常分为三种:
程序错误异常,指处理器在执行指令的过程中,检测到了程序中的错误,并由此引发的错误。
软件引发的异常。这类异常通常是into,int3和bound指令主动发起的,这些指令允许在指令流的当前点上检查实施异常处理跌条件是否满足。比如一个例子,into指令在执行的时候,将检查EFLAGS寄存器的OF标志位,如果满足为“1”的条件,那么就引发异常。
第三种是机器检查异常。这种异常是处理器型号相关的,也就是说,每种处理器都不太一样。无论如何,处理器提供了一种对硬件芯片内部和总线处理进行检查的机制,当检测到有错误的时候,将引发此异常。
根据异常情况的性质和严重性,异常又分为以下三种,并分别实施不同的特权保护。
故障(Faults)。故障通常是可以纠正的。最典型的就是处理器执行一个内存访问指令的时候,发现那个段或者页不在内存中(P=0),此时,可以在异常处理程序中予以纠正(分配内存,或者执行磁盘的换入换出操作)。返回时,程序可以重新启动并且不失连续性。当故障发生的时候,处理器把及其状态恢复到引发故障的那条指令之前的状态,在进入异常处理时,压入栈中的返回地址(CS和EIP的内容)是指向引起故障的那条指令的,而不像通常那样指向下一条指令。虚拟内存管理就是以异常为基础的。
陷阱(Traps)。陷阱中断通常在执行了解惑陷条件的指令立即产生,如果陷阱条件成立的话。陷阱通常用于调试目的,比如单步中断指令int3和溢出检测指令into。陷阱中断允许程序或者任务从中断处理过程返回后继续执行不失连续性。当陷阱异常发生的时候,转入异常处理程序之前,处理器在栈中压入陷阱截获指令的下一条指令地址。
终止(Aborts)。终止标志着最严重的错误,诸如硬件错误,系统表(GDT,LDT等)中的数据不一致或者无效。这种错误发生的时候,程序或者任务都不可能重新启动。
对于某些异常,处理器在转入异常处理程序之前,会在当前栈中压入一个称为错误代码的数值,帮助程序进一步诊断异常产生的位置和原因。
现在解释一下一些比较陌生的中断:
80486之后,处理器内部集成了浮点运算器x87 FPU,不需要再安装独立的数学协处理器,所以有些的浮点运算有关的异常不会产生(比如向量为9的协处理器段超越故障)。Wait和fwait指令用于主处理器和浮点处理部件(FPU)之间的同步。他们应当放在浮点指令之后,以捕捉任何浮点的异常。
从1993年的Pentium处理器开始,引入了用于加速多媒体处理的多媒体拓展技术(Multi-Media eXtension,MMX),该指令使用单指令多数据(Single-Instruction,Multiple-Data,SIMD)执行模式,以便在64位的寄存器内实施并行的整数运算。随着处理器的更新换代,这项技术也多次拓展,第一次被称为SSE(SIMD Extension),第二次是SSE2,第三次是SSE3。和SIMD有关的异常是从Pentium III处理器开始引入的。
bound(Check Array Index Against Bounds)指令用于检查数组的索引是否在边界之内,其格式为