这篇文章翻译自Intel 80386 Reference Programmer’s Manual的第9章。

第九章 异常和中断(Exceptions and Interrupts)

中断和异常是特殊类型的控制转移,他们执行起来有点像非编程(unprogramed)的CALL(调用)。他们改变正常的程序流去处理外部事件(external events)、报告错误( report errors)或异常条件(exceptional conditions)。中断和异常的不同之处在于中断用来处理处理器外部的异步(asynchronous)事件,而异常用来处理处理器在执行指令过程中检测到的条件。

外部中断和异常都有两个来源:

  1. 中断

    • 可屏蔽(maskable)中断,通过INTR引脚发出信号。
    • 不可屏蔽(nomaskable)中断,通过NMI(Non-Maskable Interrupt)引脚发出信号。
  2. 异常
    • 处理器检测到的(processor detected)。它们又被分为故障(faults)、陷阱(traps)和中止(aborts)。
    • 程序控制的(programmed)。指令 INTO, INT 3, INT n, 和 BOUND 可以触发异常。这些指令也被称为“软件中断”(software-interrupts),但是处理器像异常那样处理它们。

本章介绍了80386在保护模式下(protected mode)执行时,控制和响应中断的特性。

9.1 标识中断Identifying Interrupts

处理器把一个标识号(identifying number)和一个不同类型的中断或异常关联起来。

处理器通过预先分配的范围为0到31的标识符(identifiers)来识别NMI和异常。并不是这些数字都在被使用,这个范围内未分配的标识符被英特尔保留,待未来可能的拓展。

可屏蔽中断的标识符由外部中断控制器(external interrupt controllers,例如英特尔8259A可编程中断控制器(Programmable Interrupt Controller))决定,并在处理器的中断确认序列(interrupt-acknowledge sequence)中和其通信。可以由软件指定8259A PIC分配的数字。在32到255这个范围内的数字都能用。表9-1显示了中断和异常标识符的分配情况。

Table 9-1. Interrupt and Exception ID Assignments表9-1. 中断和异常ID分配Identifier(标识符)   Description(描述符)0            Divide error除法错误
1            Debug exceptions调试异常
2            Nonmaskable interrupt不可屏蔽中断
3            Breakpoint (one-byte INT 3 instruction)断点
4            Overflow (INTO instruction)溢出
5            Bounds check (BOUND instruction)边界检查
6            Invalid opcode无效操作码
7            Coprocessor not available
8            Double fault
9            (reserved)
10           Invalid TSS
11           Segment not present
12           Stack exception
13           General protection
14           Page fault
15           (reserved)
16           Coprecessor error
17-31        (reserved)
32-255       Available for external interrupts via INTR pin

根据报告异常的方式以及是否支持重新启动导致异常的指令,将异常分为故障、陷阱或中止。

故障(faults):

指的是在指令造成异常之前进行报告的异常。故障在指令开始执行之前或者执行之中被检测到。如果是在执行之中被检测到,在故障被报告的同时,机器会保存状态,以便重新执行指令。

陷阱(traps):

trap是在检测到异常的指令之后,立即在指令边界报告的异常。

中止(aborts):

中止是既不精确定位引起异常的指令,也不重新执行造成异常的程序的异常。中止用来报告严重的错误,例如硬件错误或者系统表中有不一致、非法的值。

9.2 开关中断Enabling and Disabling Interrupts

处理器只有在一条指令执行完,下一条开始前才处理中断和异常。当重复前缀用于重复一条字符串指令时,重复之间可能会发生中断和异常。因此,长字符串的操作并不会延迟中断响应。

我们可以通过一些条件和标志(flag)设置使得处理器在指令边界上禁止中断和异常。

9.2.1 NMI Masks Further NMIs

当一个NMI handler在执行时,处理器会忽略NMI引脚上的中断信号,直到下一个IRET 指令执行。

9.2.2 IF Masks INTR

IF (interrupt-enable flag)控制着是否接受INTR引脚上的外部中断信号。当IF=0INTR中断是被禁止的,反之是可用的。和其他标记位一样,收到RESET信号时,处理器会清零IF位。指令 CLI 和STI 改变IF位。

CLI (Clear Interrupt-Enable Flag) 和 STI (Set Interrupt-Enable Flag)显式改变IF(标志寄存器(flag register)中的9号位)。这些指令只能在 CPL <= IOPL时执行,否则会发生保护异常(protected exception)。

下面的操作会对IF产生隐式影响:

  • 指令 PUSHF把把所有的标志,包括IF存储到可以检查它们的栈里。
  • 任务切换并且指令 POPF 和IRET 加载标志寄存器;因此它们可用来修改IF
  • 中断通过中断门(interrupt gates)自动复位IF,并禁用中断。(本章稍后会解释中断门)

9.2.3 RF Masks Debug Faults

EFLAGS中的RF位控制调试故障(debug faults)的识别,这允许对给定指令最多抛出一次调试错误,无论该指令被重新启动多少次。(关于debugging的更多信息参阅第12章)

9.2.4 MOV or POP to SS Masks Some Interrupts and Exceptions

需要改变栈段(stack segment)的软件经常使用一对指令,例如:

MOV SS, AX
MOV ESP StackTop

如果一个中断或异常在SS已经改变但是ESP还未改变时被执行,栈指针的两部分SS:ESP在中断处理程序(interrupt handler)或异常处理程序(exception handler)中的持续是不一致的(the two parts of the stack pointer SS:ESP are inconsistent for the duration of the interrupt handler or exception handler)。

为了防止这种情况发生,80386在执行一条对于SS的 MOV 或POP指令之后,禁止NMIINTR,调试异常,单步陷阱(single-step traps)。(To prevent this situation, the 80386, after both a MOV to SS and a POP to SS instruction, inhibits NMI, INTR, debug exceptions, and single-step traps at the instruction boundary following the instruction that changes SS.)一些异常仍可能发生,即页故障(page fault)和一般保护故障。使用 LSS 指令可防止问题的发生。

9.3 中断和异常的优先级Priority Among Simultaneous Interrupts and Exceptions

如果一个指令边界上挂起多条中断或异常,处理器一次只能处理一条。中断和异常的优先级见表9-2。处理器首先处理高优先级的中断或异常,控制转移到中断处理程序的第一条指令。低优先级的异常被丢弃;低优先级的中断被挂起。当中断返回时,丢弃的异常会被恢复。

Table 9-2. Priority Among Simultaneous Interrupts and ExceptionsPriority   Class of Interrupt or ExceptionHIGHEST    Faults except debug faults
Trap instructions INTO, INT n, INT 3
Debug traps for this instruction
Debug faults for next instruction
NMI interrupt
LOWEST     INTR interrupt

9.4 中断描述符表Interrupt Descriptor Table

中断描述表(IDT)将每个中断或异常描述符和为相关事件服务的指令描述符关联起来。类似于GDT和LDTs,IDT是一个8字节的描述符的数组,不同的是,IDT的第一个条目可能包含一个描述符。为了在IDT中形成索引,处理器把中断和异常描述符乘8。因为只有256个标识符(identifier),IDT需要包含不超过256个描述符(descriptor)。可以包含少于256个条目;条目只对实际使用的中断标识符是必需的。

IDT可以驻留在物理内存中的任何位置,如图9-1,处理器通过IDT寄存器(IDDTR)定位其位置。

指令 LIDT 和SIDT操作寄存器IDTR,这两条指令都有一个显式操作数:内存中的一个6字节地址,图9-2说明了其格式。

LIDT(load IDT register)将内存操作数中的线性基址和limit值加载到IDT寄存器中。这条指令只有当CPL为0时才能执行。它经常在创建IDT时,由操作系统的初始化逻辑使用。操作系统也可能用它从一个IDT切换到另一个。

SIDT(store IDT register)把存在IDTR中的base和limit值存到内存里。这条指令能在任何特权级下执行。

9.5 中断描述符表的描述符IDT Descriptors

IDT可能包含三种描述符的任何一个:

  • 任务门(Task getes)
  • 中断门(Interrupt gates)
  • 陷阱门(trap getes)

图9-3说明了格式。(IDT中的任务门和第7章已经讨论过的任务门一样)

9.6 中断任务和中断程序Interrupt Tasks and Interrupt Procedures

就像一个CALL指令可以调用一个过程或者程序,一个中断或异常可以“调用”一个既是任务也是程序的中断处理程序。处理器使用中断或异常标识符索引IDT中的描述符来响应中断或异常。当处理器索引中断或陷阱门时,它像CALL指令调用门一样调用中断处理程序。当处理器找到一个任务门,它像CALL指令调用任务门一样进行任务切换。

9.6.1 中断程序Interrupt Procedures

如图9-4所示,一个中断门或陷阱门间接指向一个程序,它将在当前任务中的上下文(context)中执行。门的选择符指向一个在GDT或当前IDT中的的可执行段描述符(executable-segmen descriptor)。门的偏移字段指向指向中断或异常处理程序的开始。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EFVkqjTD-1643808650978)(https://raw.githubusercontent.com/DavidZyy/PicBed/master/img/20220201213304.png)]

80386像调用一个程序那样调用中断或异常处理程序。不同之处在后文中解释。

9.6.1.1 中断过程的栈Stack of Interrupt Procedure

就像有CALL指令引起的控制转移一样,一个中断或者异常处理程序的控制转移使用栈来存储信息,以便返回原来的程序。如图9-5,中断时,EFLAGS寄存器先于中断指令的指针(译注:指OLD EIP?)被放入栈中。特定类型的异常会产生一个异常码(error code),放入栈中。异常处理程序使用异常码来诊断异常。

9.6.1.2 中断程序返回Returning from an Interrupt Procedure

中断程序的返回和普通程序也不同。IRET指令用来从中断程序返回,其和RET指令很像,除了比后者的ESP多了4个字节(因为标志位被保存在栈上),并且把保存的标志位放到EFLAGS寄存器里。EFALGS寄存器的IOPL字段只有当CPL为0时才改变。IF标志位只有当CPL<=IOPL时才改变。

9.6.1.3 中断过程使用的标志位Flags Usage by Interrupt Procedure

在当前TF的值被作为EFLAGS的一部分保存在栈上之后,通过中断门和陷阱门的中断把TF(陷阱标志位)重置。通过这个步骤,处理器防止使用但不的调试活动影响中断响应。(By this action the processor prevents debugging activity that uses single-stepping from affecting interrupt response. )随后的IRET指令使用保存在栈上的EFLAGS映像恢复TF的值。

中断门和陷阱门不同的是对于IF(开关中断标志)的影响。通过中断门的中断复位IF,以便阻止其他中断干扰当前中断程序。指令使用保存在栈上的EFLAGS映像恢复IF的值。一个通过陷阱门的中断不会改变IF

9.6.1.4 中断过程保护Protection in Interrupt Procedures

管理中断过程的特权规则类似于中断过程调用;CPU不允许一个中断控制转移到一个段中的过程,如果那个段的特权级比当前特权级低(数值上更大)。破坏这条规则的尝试会导致一般保护异常。

因为中断发生的过程通常是不可预测的,这条特权规则有效地限制了中断和异常处理过程可以执行的特权级别。下面两条策略都可以用来确保特权规则不会破坏。

  • 把处理程序放在符合标准的段中。这条策略适合一些特定的异常(例如除法错误)。这样的程序必须只使用栈中对它有用的程序。如果它需要数据段中的数据,数据段需要具有特权级3,从而使其不受保护。
  • 把处理程序放在特权级0的段中

9.6.2 中断任务Interrupt Tasks

一个IDT中的任务门间接指向一个任务,如图9-6。门的选择符指向一个GDT中的TSS描述符。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tyLVtP8G-1643808650981)(https://raw.githubusercontent.com/DavidZyy/PicBed/master/img/20220202152933.png)]

当中断或异常指向IDT中的一个任务门时,任务切换发生了。用一个分离的任务处理中断有两个优点:

  • 整个上下文被自动保存
  • 中断处理程序可以通过给它一个分隔(通过它的LDT或通过它的页目录)的地址空间和其他任务隔离。

中断处理器切换任务的方式已经在第7章讨论过了。中断任务通过指令IRET返回被中断任务。

如果任务切换是被一个具有错误码的异常造成的,处理器自动把错误码放在与中断任务中要执行的第一个指令的特权级别对应的栈里。

当中断任务被一个80386操作系统使用时,实际上有两个调度器:软件调度器(操作系统的一部分)和硬件调度器(处理器中断机制的一部分)。软件调度器的设计应该考虑到硬件调度器可以在中断被启用时调度中断任务。

9.7 Error Code

对于与特定段相关的异常,处理器将错误码push到异常处理程序(无论是过程还是任务)的栈上。错误码具有图9-7的格式。错误码的格式类似于选择符的格式;但是,错误码不包含RPL字段,而是包含其他两个1位项:

  1. 如果程序的外部事件造成异常,处理器设置EXT位。
  2. 如果错误码的索引部分指向一个IDT中的门描述符,处理器设置I位(IDT位)。

如果I位没有被设置,TI位表示错误码相关于GDT(值为0)还是LDT(值为1)。剩下的14位是所涉及的段选择符的前14位。在某些情况下,栈上的错误码是null,也就是说,低阶字中的所有位都是零。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vr3zsVcn-1643808650982)(https://raw.githubusercontent.com/DavidZyy/PicBed/master/img/20220202183104.png)]

9.8 Exception Conditions

待译。

9.8.14 中断14——页错误 Interrupt 14 – Page Fault

当分页打开(PG=1),而且处理器在将线性地址转化为物理地址的过程中检测到下面两个条件之一时,会发生这个异常:

  • 地址转换所需的页目录项或页表项的present位为零。
  • 当前过程没有访问指定页的足够权限。

处理器向页面错误处理程序提供两项信息,帮助诊断异常并从异常中恢复:

  • 一个栈上的错误码。一个页错误的错误码的格式和其它异常的不同(见图9-8)。错误码向异常处理程序提供三项信息:

    1. 异常是由不存在的页引起的还是由访问权限破坏引起的。
    2. 在异常发生时,处理器是在用户级还是管理员级执行。
    3. 造成异常的内存访问是读还是写。
  • CR2 (control register two,2号控制寄存器)。处理器将造成异常的访问的线性地址存在其中(见图9-9)。异常处理程序可以使用这个地址定为相应的页目录项和页表项。如果在执行页面错误处理程序期间可能发生另一个页面错误,则处理程序应该将CR2压入堆栈。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5d867CIi-1643808650983)(https://raw.githubusercontent.com/DavidZyy/PicBed/master/img/20220202203222.png)]

9.8.14.1 任务切换期间的页错误Page Fault During Task Switch

处理器在任务切换期间可能访问四个段中的任何一个:

  1. 把原任务的状态写到那个任务的TSS中。
  2. 读取GDT来定位新任务的TSS描述符。
  3. 读取新任务的TSS,从TSS中检查段描述符的类型。
  4. 为了验证存储在新TSS中的段寄存器,可能读取新任务的LDT。

访问这些段中的任意一个可能引起页错误。在后面两种情况,异常发生在新任务的上下文。指令指针指向新任务的下一条指令,而非造成任务切换的指令。如果操作系统在设计上允许页错误在任务切换期间发生,页错误处理程序应该通过一个任务门调用。

9.8.14.2 栈指针不一致的页面错误Page Fault with Inconsistent Stack Pointer

特别注意确保一个页面错误不会导致处理器使用一个无效的堆栈指针(SS:ESP)。为8086系列的早期处理器写的软件经常使用一对指令来改变一个新栈,例如:

MOV SS, AX
MOV SP, StackTop

对于80386,因为第二条指令访问内存,所以在SS被更改之后,但在SP收到相应的更改之前,可能会出现页面错误。在这种情况下,栈指针的两部分SS:SP(对于32位是SS:ESP)是不一致的。

如果对于页错误的处理使得栈切换到一个定义良好的栈,处理器不会使用不一致的栈指针(即,处理程序是一个任务或一个更高优先级的程序)。然而,如果错误处理程序被一个陷阱或者中断门调用并且页错误发生在和错误处理程序相同的优先级下,处理器将尝试使用被当前(无效的)栈指针指示的栈。

在实现分页和在错误任务中处理页错误(使用陷阱或中断门)的系统中,执行在和页错误处理程序相同优先级的软件应该初始化一个新栈,通过使用新的LSS指令而不是上面显示的指令对。当页错误处理程序执行在优先级优先级0(通常情况),问题的范围局限于特权级0的代码,通常是操作系统的内核。

9.9 Exception Summary

表9-6总结了386识别的异常。

Table 9-6. Exception SummaryDescription               Interrupt   Return Address  Exception     Function That Can Generate
Number      Points to       Type          the Exception
Faulting
InstructionDivide error               0          YES             FAULT         DIV, IDIV
Debug exceptions           1
Some debug exceptions are traps and some are faults.  The exception
handler can determine which has occurred by examining DR6.  (Refer to Chapter 12.)
Some debug exceptions are traps and some are faults.  The exception
handler can determine which has occurred by examining DR6.  (Refer to Chapter 12.) Any instruction
Breakpoint                 3          NO              TRAP          One-byte INT 3
Overflow                   4          NO              TRAP          INTO
Bounds check               5          YES             FAULT         BOUND
Invalid opcode             6          YES             FAULT         Any illegal instruction
Coprocessor not available  7          YES             FAULT         ESC, WAIT
Double fault               8          YES             ABORT         Any instruction that can
generate an exception
Coprocessor Segment
Overrun                    9          NO              ABORT         Any operand of an ESC
instruction that wraps around
the end of a segment.
Invalid TSS               10          YES             FAULT
An invalid-TSS fault is not restartable if it occurs during the
processing of an external interrupt.        JMP, CALL, IRET, any interrupt
Segment not present       11          YES             FAULT         Any segment-register modifier
Stack exception           12          YES             FAULT         Any memory reference thru SS
General Protection        13          YES             FAULT/ABORT
All GP faults are restartable. If the fault occurs while attempting to
vector to the handler for an external interrupt, the interrupted program is
restartable, but the interrupt may be lost.  Any memory reference or code
fetch
Page fault                14          YES             FAULT         Any memory reference or code
fetch
Coprocessor error         16          YES             FAULT
Coprocessor errors are reported as a fault on the first ESC or WAIT
instruction executed after the ESC instruction that caused the error.        ESC, WAIT
Two-byte SW Interrupt     0-255       NO              TRAP          INT n

9.10 Error Code Summary

表9-7总结了每个异常可用的错误信息

Table 9-7. Error-Code SummaryDescription                       Interrupt     Error Code
NumberDivide error                       0            No
Debug exceptions                   1            No
Breakpoint                         3            No
Overflow                           4            No
Bounds check                       5            No
Invalid opcode                     6            No
Coprocessor not available          7            No
System error                       8            Yes (always 0)
Coprocessor Segment Overrun        9            No
Invalid TSS                       10            Yes
Segment not present               11            Yes
Stack exception                   12            Yes
General protection fault          13            Yes
Page fault                        14            Yes
Coprocessor error                 16            No
Two-byte SW interrupt             0-255         No

80386异常和中断相关推荐

  1. arm b bl 地址无关码_ARM_异常和中断

    ARM_异常和中断 问题1.中断向量表为于存储器的什么位置? ARM7系列,除ARM720T可以放高端地址,ARM9或更高都放高端地址上. 2.FIQ或IRQ异常返回指令是什么? 答案见下面.... ...

  2. 传输文件过程中遇到异常被中断

    传输文件过程中遇到异常被中断 2012/1/13 环境:使用的是91手机助手,XP系统,台式机的前置USB接口 , 行为:向手机上传输文件 错误:弹出"传输文件过程中遇到异常被中断 AFCF ...

  3. 《Cortex-M0权威指南》之体系结构---异常和中断

    <Cortex-M0权威指南>之体系结构---异常和中断 参考文章: (1)<Cortex-M0权威指南>之体系结构---异常和中断 (2)https://www.cnblog ...

  4. 浅析arm的异常、中断和arm工作模式的联系

    浅析arm的异常.中断和arm工作模式的联系 参考文章: (1)浅析arm的异常.中断和arm工作模式的联系 (2)https://www.cnblogs.com/douzi2/p/5112743.h ...

  5. Linux内核--异常和中断的区别

          相信大家都知道非常著名的两个名词:异常和中断,不过,你真的理解这两个名词在说什么吗?它们之间有什么区别呢?       1.中断       大家都知道,当我们在敲击键盘的同时就会产生中断 ...

  6. CMSIS对异常和中断标识符、中断处理函数名以及中断向量异常号都有严格的要求。

    CMSIS:Cortex Microcontroller Software Interface Standard CMSIS对异常和中断标识符.中断处理函数名以及中断向量异常号都有严格的要求.异常和中 ...

  7. windowsCE异常和中断服务程序初探

    windowsCE异常和中断服务程序初探 ---------by nasiry 转载请说明出处 1.中断/异常相量的装入和执行方式. 中断和异常都是异步发生的事件,当该事件发生,系统将停止目前正在执行 ...

  8. windowsCE异常和中断服务程序初探(=)

    继续上次的内容,在上次的分析中我们已经对SWI,FIQ,IRQ的流程有了一个大概的认识,下面继续对DataAbort和PrefetchAbort以及公共分发程序CommonHandler进行一下认识, ...

  9. Cortex-M0(3)---ARM Cortex-M0 异常与中断

    ARM Cortex-M0 异常与中断 异常类型及编号  Cortex-M0的每个异常源都有一个单独的编号:  1~15内部系统异常:Reset(1), NMI(2), H/W Error(3), S ...

  10. M0/M3的异常和中断

    1. Cortex-M3的异常/中断屏蔽寄存器组 注:只有在特权级下,才允许访问这3个寄存器. 名 字 功能描述 PRIMASK 只有单一比特的寄存器.置为1后,就关掉所有可屏蔽异常,只剩下NMI和硬 ...

最新文章

  1. 《构建之法》之第8、9、10章读后感
  2. python做图像识别好还是c++好_OpenCV人脸检测(C++/Python)
  3. was not declared in this scope
  4. ASP.NET Core中使用令牌桶限流
  5. 笨方法“学习python笔记之字典
  6. 人工智能TensorFlow工作笔记009---认识TensorFlow中的会话
  7. 【洛谷】 3264 [JLOI2015] 管道连接
  8. Java后台调用API的方法
  9. pythonscrapy爬虫ip代理池_Scrapy 框架插件之 IP 代理池
  10. 相比于 Java 10 的 var, 更期待 Java 11 支持多行字符串
  11. PDF文件不能正常显示问题的原因及解决方法(图文)
  12. 程序员在哪能接到私单?
  13. cocos creator 使用anysdk接入admod
  14. 为什么说美团的天花板是美团自己?
  15. 从 Angular Component 和 Directive 的实例化,谈谈 Angular forRoot 方法的命令由来
  16. 酷我音乐盒在听一遍就自己默认下载…
  17. android:completionthreshold=1,android:completionThreshold=1是哪个组件的属性( )
  18. Base58原理及代码
  19. python获取当日凌晨时间戳
  20. 微信小程序之小试牛刀

热门文章

  1. 智能电视怎么安装鸿蒙,智能电视如何通过手机电脑安装第三方软件,两种操作方法亲测可用...
  2. 【CGAL】编译(windos)
  3. 优点电子签章系统无法解除_电子签章常见问题解答
  4. 【专题】拉格朗日中值定理求极限
  5. 华硕 Asus TUF B360M+INTEL i5+Sapphire AMD VEGA56黑苹果EFI引导文件
  6. Eclipse安装漂亮的Darkest Dark Theme主题步骤(超详细)
  7. VS编程,几个好用的Visual Studio插件推荐(二)
  8. 图形2.5 Bump Map的改进(凹凸映射)
  9. azure微软文字转语音工具​AzureTools​使用
  10. antd使用TimePicker时报错