x86保护模式-七中断和异常

386相比较之前的cpu   增强了中断处理能力   并且引入了 异常概念
一 80386的中断和异常
为了支持多任务和虚拟存储器等功能,386把外部中断称为中断    把内部中断称为异常
最多支持256中断或异常
1.中断
中断是由异步的外部事件引起的。外部事件及中断响应与正执行的指令没有关系。
通常中断对应i/o操作的完成,cpu中intr引脚接受外部的可屏蔽的中断请求,NMI引脚接受外部不可屏蔽的中断请求。
EFLAGS标志寄存器中的IF标志决定是否屏蔽可屏蔽的中断请求
intr发出中断请求的同时还有一个8位的中断向量。cpu根据向量号来决定下一步的操作。8059a能够设置向cpu提供向量号,处理中断请求的优先级。
8259级联,最多可用 1片主帖+8片从片, 每片从片有8个外部中断请求IR0~IR7,
主片的IR0~IR7引脚分别连接8个从片的INT引脚。最多可有 8x8=64个外部中断请求。
 
cpu不屏蔽来自NMI的中断请求,响应NMI中断时,不从外部硬件接收中断向量号。固定的向量号为2   。为了不可屏蔽的嵌套,每当接受一个NMI中断,cpu就在内部屏蔽了再次响应NMI,这一屏蔽过程直到执行中断返回指令IRET后才结束。
所以NMI处理程序应该以IRET指令结束。
2.异常
异常时80386在执行指令期间检测到不正常的或非法的条件所引起的。与正在执行的指令有直接的联系。
例如  除法指令   除数等于0时。特权级不正确,指令不能成功完成。
软中断指令“INT n”和“INTO”也归类于异常而不称为中断,是因为执行这些指令产生异常事件。
386识别多种不同类别的异常,并且赋予每一种类别以不同的中断向量号。异常发生后,cpu响应异常,根据向量号转到相应的异常处理程序。
根据引起异常的程序是否可被恢复和恢复点不同,把异常分类为故障fault,陷阱trap和中止abort。我们把对应的异常处理程序分别称为故障处理程序、陷阱处理程序和中止处理程序。
故障是在引起异常的指令之前,把异常情况通知给系统的一种异常。故障是可以排除的。当控制转移到故障处理程序时,所保存的断点cs及eip的值指向引起故障的指令。这样,在故障处理程序把故障排除后,执行IRET返回到引起故障的程序继续执行时,刚才引起故障的指令可重新得到执行。
这种重新执行,不需要操作系统软件的额外参与。故障的发先可能在指令执行之前,也可能在指令执行期间。
如果在指令执行期间检测到故障,那么中止故障指令,并把指令的操作数恢复为指令开始执行之前的值。这可保证故障指令的重新执行得到正确的结果。   
例如,一条指令执行期间,发现段不存在,那么就停止该指令的执行,并通知系统产生段故障,对应的段故障处理程序可通过加载该段的方法来排除故障,之后,原指令就可以成功执行,至少不再发生段不存在的故障。
陷阱是在引起异常的指令后,把异常情况通知给系统的一种异常。当控制转移到异常处理程序时,所保存的断点cs及eip的值指向引起陷阱的指令的下一条要执行的指令。下一条要执行的指令,不一定就是下一条指令(例如call 指令)。因此陷阱处理程序并不能总根据保存的断点,反推确定出产生异常的指令。在转入陷阱处理程序时,引起陷阱的指令应正常完成,它有可能改变了寄存器或存储单元。
软中断指令、单步异常是陷阱的例子。
中止是在系统出现严重情况时,通知系统的一种异常。引起中止的指令是无法确定的。产生中止时,正执行的程序不能被恢复执行。系统接收中止后,处理程序要重新建立各种系统表格,并可能重新启动操作系统。硬件故障和系统表中出现非法值或不一致的值是中止的例子

3.优先级

在一条指令执行期间,入检测到不只一个中断或异常,那么按下边所列优先级通知系统。把优先级最高的中断或异常通知系统,其他优先级较低的异常被废弃,而优先级较高的中断则保持悬挂
 
二  异常的类型
中断和异常一样都分为多种类型
1.386识别的异常
多种不同类别的异常及赋予的对应中断向量号如下表所示。
某些异常还可以出错码的形式提供一些附加信息传递给异常处理程序,出错代码列表中的“无”表示没有出错代码,“有”表示有出错代码。

 保护模式下的某些中断向量号的分配与实模式的中断向量号发生冲突。实模式下的中断向量号的分配基于pc微机系统的8086/8088cpu,上表中的中断向量号的分配是80386所规定的。实际上8086/8088   保留了这些发生冲突的中断向量号。尽管有冲突,80386需要向下兼容,原因是80386的实模式下,几乎不发生哪些中断向量号与外部硬件中断请求时所提供的中断向量号存在冲突的异常。需要注意的是,在保护模式下必须重新设置8259a中断控制器,以产生不予异常相冲突的硬件中断向量。
2.故障类异常
当发生故障,控制转移到故障处理程序时,所保存的断点cs及eip的值指向引起故障的指令,以便在排除故障后恢复执行
a 除法出错故障   异常0
除法出错时一种故障。当执行DIV指令或IDIV指令时,如果除数等于0或者商太大,以至于存放商的操作数容纳不下
此故障没有出错码
    b 边界检查故障  异常5
如果BOUND指令发现被测试的值超过了指令中给定的范围,那么就发生边界检查故障。无出错码
c 非法操作码故障 异常6
如果386不能把cs和eip所指向存储单元的位模式识别为某条指令的部分,那么就发生非法操作码故障。当出现如下情况时   发生这样的故障    cs:ip指向的位置不是指令
(1)操作码字段的内容不是一个合法的386指令代码
(2)要求使用存储器操作数的场合,使用了寄存器操作数
(3)不能被加锁的指令前使用了LOCK前缀。

非法操作码故障不提供错误码

d 设备不可用故障(异常7)
不支持387协处理器,可用该异常的处理程序代替协处理器的软件模拟器。发生任务切换时,使得只有在新任务使用浮点指令时,才进行387寄存器状态的切换。设备不可用故障不提供出错码。
(1)执行浮点指令时,cr0中em位或ts位为1。
(2)执行wait指令时,cr0中的ts位及em位都为1。
(3)异常的处理程序必须是一个程序而不是任务,否则当处理程序发布一条IRET指令时,80386就设置ts位。然后协处理器再次执行这个发生故障的指令,发现ts是置位的。因此再次发生异常7,结果就是死循环。处理程序能通过陷阱门被调用,因为执行期间可以允许中断
e 无效tss故障  (异常0ah)
当正从任务状态段tss装入选择子时,如果发生了除了段不存在外的段异常时,就发生此故障。
1进入故障处理程序时,保存的cs及eip指向发生故障的指令
2或者该故障作为任务切换的一部分发生时,指向任务的第一条指令
3提供出错码   
其中选择子部分指向引起故障的tss的选择子。16位的出错码的主要成分是选择子,指向引起故障的tss的选择子。高13位是选择子的索引部分,TI位是描述符表指示位。
上图为异常出错码的一般格式。从途中可见出错码不含选择子的rpl  而由IDT位和EXT位代替。当处理某一异常或外部中断时,又发生了某种异常,那么EXT位置1.当从中断描述符表IDT中读出表项并产生异常时,IDT位置1,这只在中断或异常的处理期间才会发生。当没有选择子时,构成出错码选择子部分的值为0。
4.引起无效tss故障的原因如下
a tss描述符中的段限长小于103
b 无效的LDT描述符,或者LDT未出现
c 堆栈段不是一个可写段
d 堆栈段选择子索引的描述符超出描述符表界限
e 堆栈段DPL与新的cpl不匹配;
f 堆栈段选择子的rpl不等于cpl
g 代码段选择子索引的描述符超出描述符表界限
h 代码段选择子不指向代码段
i 非一致代码段的dpl不等于新的cpl
j 一致代码段的dpl大于新的cpl
k 对应ds   es   fs 或gs的选择子指向一个不可读的段,例如系统段
l 对应ds   es   fs 或gs的选择子索引的描述符超出描述符表的界限
f 段不存在的故障(异常0bh)
处理器在把描述符装入非ss寄存器的高速缓冲时,如果发现描述符其他方面有效,而p位为0表示(对应段不存在),那么在引用此描述符时就发生段不存在故障。有关ss段的情形纳入堆栈段故障。在进入故障处理程序时,保存的cs及eip执行发生故障的指令;或者该故障作为任务切换的一部分发生时,指向任务的第一条指令。
段不存在故障提供了一个包含引起该故障的段选择子的出错代码。出错码的格式如上图所示。选择子索引部分为引起段不存在故障的段描述符选择子的索引。
g 堆栈段故障(异常0ch)
cpu检测到用ss寄存器进行寻址的段有关的某种问题时,就发生堆栈段故障。在进入故障处理程序时,保存的cs级eip指向发生故障的指令;或者该故障作为任务切换的一部分发生时,指向任务的第一条指令。堆栈段故障提供一个出错码,出错码的格式也如上如所示
引起堆栈段故障的原因
(1)堆栈操作时,偏移超出段界限所规定的范围。这种情况下的出错码是0.例如PUSH操作时,堆栈溢出。
(2)在由特权级变换所引起的对内层堆栈操作时,偏移超出段界限所规定的范围。这种情况下的出错码包含有内层堆栈的选择子。
(3)装入到ss寄存器(高速缓冲寄存器)的描述符中的存在位为0.这种情况下的出错码包含有对应的选择子。
第一中情况容易辨别。第2和3中情况的辨别需要通过判断出错码所含的选择子所指示的描述符中的存在位进行,如果存在位为1,那么是第二种情况,否则是第三种情况。
h 通用保护故障(异常0dh)
除了明确列出的段异常外,其他的段异常都被视为通用保护故障。在进入故障处理程序时,保存的cs及eip指向发生故障的指令;或者该故障作为任务切换的一部分发生时,指向任务的第一条指令。通用保护故障提供一个出错码,出错码的格式也如上图所示。
根据处理程序可能作出的响应,通用保护故障可分为如下两类:
(1)违反保护方式,但程序无须中止的异常。此类故障的出错码为0.这种异常在应用程序执行特权指令或I/O访问呢时发生,支持虚拟8086程序的系统或支持虚拟i/o访问的系统需要模拟这些指令,并在模拟完成产生故障的指令后,重新执行被中断的程序。
(2)违反保护方式,并导致程序终止的异常。这类故障提供的出错码可能为0  ,也可能不是0(能确定选择子时)。引起此类的故障原因
a 向某个只读数据段或代码段写;
b 从某个智能执行的代码段读出;
c 将某个系统段描述符装入到数据段寄存器ds、es、fs、gs或ss;
d 将控制转移到一个不可执行的段;
e 在通过段寄存器cs、ds、es、fs或gs访问内存时,偏移超出段界限
f 当访问某个描述符表时,超过描述符表段界限;
把pg位为1但pe位为0的控制信息装入到cr0寄存器;
切换到一个正忙的任务。
 
对上述两类通用保护故障的辨别,可通过检查引起故障的指令和出错码进行。如果出错码非0,那么肯定是第二类通用保护故障。如果
出错码是0,那么需要进一步检查引起故障的指令,以确定它是否是系统支持的可以模拟的指令。
i 页故障 异常0eh 略
j 协处理器出错 异常10h  
协处理器出错故障指示协处理器发生了未被屏蔽的数字错误,如上溢或下溢。在引起故障的浮点指令之后的下一条浮点指令
或WAIT指令,把协处理器出错作为一个故障通知给系统。协处理器出错故障不提供出错码。
3.陷阱类异常

a 调试陷阱  异常1
调试异常有故障类型,也有陷阱类型。调试程序可以访问调试寄存器dr6  以确定调试异常的原因和类型。调试异常不提供出错码。
b 单字节 INT3  异常3
INT3是一条特别的单字节 INT n 指令 ,调试程序可利用该指令支持程序断点。INT3指令被看成是一种陷阱。而不是一个中断。当由于执行INT3指令进入异常3处理程序时,被保存的cs和eip指向紧跟INT3的指令,即INT3后面的字节。INT3陷阱不提供出错码。
c 溢出  异常4
INTO指令提供条件陷阱。如果OF标志为1,那么INTO指令产生陷阱;否则不产生陷阱,继续执行INTO后面的指令。在进入溢出处理程序时,被保存的cs和eip指向INTO指令的下一条指令。溢出陷阱不提供出错码。
4.中止类异常
a 双重故障异常 异常8
当系统正在处理一个异常时,如果又检测到一个异常,处理器试图向系统通知一个双重故障,而不是通知第二个异常。双重故障属于中止类异常,所以在转入双重故障处理程序时,被保存的cs和eip可能不指向引起双重故障的指令,而且指令的重新启动不支持双重故障。  出错码为0
当正处理一个段故障异常时,有可能又产生一个页故障。在这种情况下,通知给系统的是一个页故障异常而不是双重故障异常。但是,如果正处理一个段故障或页故障时,又一个段故障被检测到;或者如果正处理一个页故障时,又一个页故障被检测到,那么就引起双重故障。
当正处理一个页故障时,又一个段或页故障被检测到,那么处理器暂停执行指令,并进入关机方式。关机方式类似于处理器指令一条HLT指令后的状态:处理器空转,并维持到处理器接收到一个NMI中断请求或者被重新启动为止。在关机方式下,处理器不响应INTR中断请求。
双重故障通常指示系统表出现严重的问题,例如段描述符表、页表或中断描述符表出现问题。双重故障处理程序在重建系统表后,可能不得不重新启动操作系统。
b 协处理器段越界  异常9
协处理器段越界异常属于中止类异常,这是因为引起该异常的指令不能被重新启动。但更浮点指令操作数超出段界限时,产生该中止异常。协处理器段越界异常不提供出错码。在异常处理程序入口保存的cs及eip指向被中止的指令。这种中止不是系统的中止,而是只影响到这种异常时正执行的指令所在的程序。
 
三  中断和异常的转移方法

x86保护模式-七中断和异常的更多相关文章

  1. ASM:《X86汇编语言-从实模式到保护模式》第17章:保护模式下中断和异常的处理与抢占式多任务

    ★PART1:中断和异常概述 1. 中断(Interrupt) 中断包括硬件中断和软中断.硬件中断是由外围设备发出的中断信号引发的,以请求处理器提供服务.当I/O接口发出中断请求的时候,会被像8259 ...

  2. x86 保护模式 十 分页管理机制

    x86   保护模式  十  分页管理机制 8.386开始支持分页管理机制 段机制实现虚拟地址到线性地址的转换,分页机制实现线性地址到物理地址的转换.如果不启用分页,那么线性就是物理地址 一  分页管 ...

  3. X86保护模式 八操作系统类指令

    X86保护模式  八操作系统类指令 通常在操作系统代码中使用,应用程序中不应用这些指令 指令分为三种:实模式指令,任何权级下使用的指令.实模式权级0下可执行的指令和仅在保护模式下执行的指令 一  实模 ...

  4. x86保护模式 任务状态段和控制门

    x86保护模式    任务状态段和控制门 每个任务都有一个任务状态段TSS     用于保存任务的有关信息     在任务内权变和任务切换时  需要用到这些信息    任务内权变的转移和任务切换  一 ...

  5. x86保护模式 实模式与保护模式切换实例

    x86保护模式     实模式与保护模式切换实例 实例一 逻辑功能   以十六进制数的形式显示从内存地址110000h开始的256个字节的值    实现步骤: 1  切换保护方式的准备 2. 切换到保 ...

  6. x86保护模式 控制寄存器和系统地址寄存器

    控制寄存器和系统地址寄存器 控制寄存器    crx cr0   指示cpu工作方式的控制位  包含启用和禁止分页管理机制的控制位  包含控制浮点协处理器操作的控制位   注意必须为0的位 cr2和c ...

  7. x86保护模式-六 控制转移

    控制转移可以分为两大类  :同一任务内的控制转移    和   任务间的控制转移(任务切换) 同一个任务内的控制转移可以分为段内转移 .特权级不变的段间转移和特权级改变的段间转移 段内转移与实模式相同 ...

  8. x86保护模式 二 分段管理机制

    分段管理机制 段选择子和偏移地址的二维虚拟地址转换为一维的线性地址 一  段定义和虚拟地址到线性地址的转换 三个参数定义段:段基地址    段界限  和段属性    同时也是段描述符的结构 段基地址为 ...

  9. 保护模式篇——TLB与CPU缓存

    写在前面   此系列是本人一个字一个字码出来的,包括示例和实验截图.由于系统内核的复杂性,故可能有错误或者不全面的地方,如有错误,欢迎批评指正,本教程将会长期更新. 如有好的建议,欢迎反馈.码字不易, ...

随机推荐

  1. JS字符串处理方法

    1.字符方法charAt()和charCodeAt();这两个方法都接收一个参数例:<script>var stringValue = "hello world"; s ...

  2. uvm_driver——老司机带带我

    文件:src/comps/uvm_driver.svh类: uvm_driver uvm_driver继承(C++中叫继承)自uvm_component,其中定义了两个Ports:seq_item_p ...

  3. cacti图形字符乱码

    环境:最小化centos+cacti 问题:图形监控界面字符全部乱码,如下图 解决方法:从windows下面拷贝一个ttf文件到/usr/share/fonts下面,刷新页面,字符就正常显示了.

  4. 系统妈Ghost Win10 64位快速安装版 V2016年2月

    系统妈Ghost win10 64位快速安装版 V2016年2月,更新了最新系统补丁,升级系统版本号为2016年2月份.这款累积更新补丁会取代之前的版本.本系统还附带最常用的装机必备软件.QQ等. 系 ...

  5. 洛谷P1628 合并序列

    题目描述 有N个单词和字符串T,按字典序输出以字符串T为前缀的所有单词. 输入输出格式 输入格式: 输入文件第一行包含一个正整数N: 接下来N行,每行一个单词,长度不超过100: 最后一行包含字符串T ...

  6. Python 目录和文件基本操作

    今天在写一个小工具的过程中发现对目录和文件的基本操作不是很熟,特此把遇到的常用操作总结汇总下. 获取当前路径:os.getcwd() 目录操作:1.创建目录:os.mkdir('目录名')2.创建多级 ...

  7. IOS音频视频

    视频播放 MediaPlayer.framework MPMoviePlayerViewController VS MPMoviePlayerController MPMoviePlayerViewC ...

  8. HDU 6069 Counting Divisors(区间素数筛法)

    题意:...就题面一句话 思路:比赛一看公式,就想到要用到约数个数定理 约数个数定理就是: 对于一个大于1正整数n可以分解质因数: 则n的正约数的个数就是 对于n^k其实就是每个因子的个数乘了一个K ...

  9. HITICS || 2018大作业 程序人生 Hello's P2P

    摘  要 本文通过分析一个hello.c的完整的生命周期,从它开始被编译,到被汇编.链接.在进程中运行,讲解了Linux计算机系统执行一个程序的完整过程. 关键词:操作系统,进程,程序的生命周期 目 ...

  10. PHP 递归无限极下级

    下面是自己用到的一些递归方法,当然都是借鉴的,各位看官请勿怪 第一种 有层级 $array = array( array('id' => 1, 'pid' => 0, 'n' => ...