x86异常处理与中断机制(2)中断向量表

补充:事件不仅包含中断和异常,还包含系统调用,这个属于用户主动请求的事件。

上一节,只有一个溢出异常,那么,如果很多异常、中断呢?(中断向量表)

另外,之前0号地址只能存储两条指令,如果需要更多指令怎么办?(地址的位置以及对应程序大小应该更灵活)

注意,中断服务程序包含(保存现场,调用处理方法(主体),恢复现场)

我们在遇到中断之后,需要执行的步骤,我们简化一下

  1. CPU做一些硬件处理工作(识别中断源,关中断,当前指令(或下一条指令)地址压栈,FLAGS寄存器压栈)
  2. 到处理中断的程序地址(这里的程序是中断服务程序)
  3. 执行中断服务程序(包含保护现场,执行处理程序(这个才是主体部分),恢复现场,返回原程序)
  4. 继续执行原有程序

在不同的时代,中断的处理都是这个过程,只不过每个过程具体的执行发生了变化,且越来越复杂,我们依次看一下。

1 时代1:UNIVAC时代,仅有固定地址中断处理

在最初的计算机时代,只有很少的内部中断和外部中断。
在这里插入图片描述内个时候的中断服务程序,是固定的地址,并且程序的大小也相对受限。

例如出现了算数溢出,那么就会跳转到地址0执行中断服务程序

在这里插入图片描述
不仅如此,这个时候的中断服务程序几乎是

  • 固定地址
  • 固定大小

因此灵活性很差,不过由于很少,所以还好。

到了后来,中断越来越多,因此就有了中断向量表,下面看看8086时代吧。

2 时代2:8086时代,实模式 + 中断向量表

这个时代,中断已经较多了,管理中断的方式也更加灵活了。

在这里插入图片描述
8086采用的是实模式,也就是说,进入CPU指令中的地址,就是实际的物理地址。

在8086的1MB内存中,有专门的中断向量表区,从地址0开始的1K字节,它用于存放中断服务程序的地址,也就是存放CS:IP

每对CS:IP占用4个字节,因此1KB的空间,最多可以支持256种中断
在这里插入图片描述
CS:IP,CS在前,IP在后,因此CS在高地址,IP在低地址,又因为是小端模式,因此IP的高字节是高位,低字节是低位;CS同理。

这样一来,实际的中断服务程序的位置,是根据这些CS:IP的值确定的,而它们在内存中是可以修改的,因此

  • 中断服务程序的位置可变
  • 程序的大小可改

并且这些中断服务程序的位置是任意的,只要能够与中断向量表对应上即可。

同时,不同的中断服务程序,位置没有关联,放哪里都行。在实模式的8086之下,只需要CS:IP就可以确定实际内存的位置。
在这里插入图片描述
在这个时代,中断服务程序的位置了大小更加灵活,变成了间接获取,因为加了一个中断向量表。

在这里插入图片描述
注意,这个时候有5种类型的中断,并不是5个中断,这个时候涉及到的内部中断有4个,外部中断有1个,而这个外部中断,是8259A芯片发出的,该芯片外面可以连接很多个外设。

在这里插入图片描述
我们来看看这个时代中断处理的示意图。

在这里插入图片描述

3 时代3:80386时代,保护模式 + 中断向量表

这个时代就有点复杂了,引入了保护模式,同时增加了一些中断类型,这也是Linux 0.11内核对应的CPU。

在这里插入图片描述圈住的部分是80386支持的中断类型,int0 ~ int16,其中int15未定义,可以在手册中查到。
在这里插入图片描述

3.1 保护模式下的寻址方式

首先,保护模式下,依然是CS:EIP的形式,但是由于EIP已经足够寻址4GB,因此CS不再作为位数扩展的功能了,它的功能发生了改变。

在这里插入图片描述
在保护模式下,段寄存器依然是16位,它们变成了段选择子寄存器,先从最简方式描述地址的生成方法

  1. 通过段选择子寄存器找到8字节大小的段描述符
  2. 根据段描述符的内容获取段基址(32位)
  3. 段基址EIP组合(==应该就是相加吧?==基址 + 偏移地址),得到地址
  4. 注意: 目前可以知到这个地址是给CPU看的,它应该是虚拟地址,现在先不管,先当成通过这个地址就能够访问到内存的指定位置。

是不是比实模式复杂多了,下面,进一步展开细节

通过段选择子寄存器(此后均以CS举例说明),怎么找到对应的段描述符?在这里插入图片描述

  1. 计算机启动进入实模式
  2. 填好GDT
  3. 设置好GDT的初始地址放入GDTR寄存器中

在保护模式下, CS + GDTR获取对应的描述符(0~8191),这样,我们就获取了代码段的描述符了。

接下来我们看看这个描述符

  1. 这个描述符有8192个,也就是2^13,而一个描述符有2^3 = 8个字节,因此一共占用了2^16个内存单元,也就是64KB,CS寄存器是16位的,这是它能够访问的极限,这样,通过GDTR基址 + CS偏移的方式,能够访问到每一个描述符表。
  2. 再看每一个描述符的结构
    在这里插入图片描述
    它有8个字节的大小,其中有四个字节是段基址,就是这个段基址与EIP组合,形成最终的要访问内存的(虚拟)地址。其他的自己还涉及到权限以及界限,先不管是干啥的。

段描述符的内容是什么,怎么获取段基址

上面已经说明了。

3.2 保护模式下的中断操作

上面一小节,经历了一系列复杂过程,终于说明了保护模式下如何寻址,真的很复杂啊……下面说明一下中断操作过程。其实最主要说明的还是中断服务程序位置这个过程。

在这里插入图片描述
在保护模式下,也有一个IDTR中断描述符表寄存器,还有一个IDT中断描述符。

这个IDT同样是支持256种类型的中断的,每个描述符表项占8个字节,因此一共占用2KB。

IDTR提供的是IDT的基址,然后CPU获取中断号之后,根据中断号 * 8 + IDTR定位对应的描述符。

对于中断描述符

  • 字节0167四个字节对应的是32位地址,也就是EIP的值
  • 字节23对应的是CS的值
  • 有了CS:EIP就可以通过上一小节的方式找到对应的地址,从而找到中断服务程序入口地址
    (这个过程其实与CS:IP类似,只不过麻烦了点)

折腾了这么一大圈,终于找到中断服务程序了……

3.3 小结

这个太复杂了,我们简单总结一下吧。

首先,保护模式下的寻址方式更复杂了,引入了全局描述符表,虽然依然是CS:EIP,但是其计算方式更加复杂了。

其次,保护模式下的中断处理更复杂了

  • 以前固定位置的中断向量表,变成了任意位置的中断描述符表IDT,通过IDTR中断类型号计算得到中断描述符
  • 再通过中断描述符的内容获取CS:EIP,再获取对应中断服务程序的入口地址

我们可以看到,模式越来越复杂间接程度越来越高,设置的自由度提高,安全性也提高了。

在这里插入图片描述

思想:太固定死板怎么办?加个固定的中转站!通过改变中转站,来实现灵活地分配目标

这几个时代的发展过程,可以说中转站越来越多,越来越复杂,灵活度越来越高。

小结

本篇内容,贯彻的是中断处理的找中断服务程序的过程。

可以看到

  1. UNIVAC时代非常直接地找到地址
  2. 8086时代提供了固定位置中断向量表,间接地找到CS:IP,寻址方式是直接的
  3. 80386时代提供了任意位置的中断描述符表,间接地获取CS:EIP,寻址方式也是间接的,需要通过全局描述符表GDT获取段基址,从而获取内存地址

不管怎样,时代的发展使得根据中断类型号,找到中断服务程序这个过程越来越复杂,灵活度也越来越高。

后面会介绍中断处理的其他过程,最后结合Linux 0.11内核源代码,使得软硬件对应上。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/384611.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

x86异常处理与中断机制(3)中断处理过程

上一节讲完了根据中断类型号找中断服务程序的过程,现在着重说明一下更加完整的中断处理过程吧。 本节以8086时代的中断处理过程为例进行说明,主要分两大部分 硬件处理软件处理 需要注意,这不是绝对的,得看实际情况,…

Linux 0.11 内核解析:中断相关(1)asm.s文件中断处理分析

0 源代码 有两个版本的,一个是带中文注释,Intel格式的;一个是不带注释是AT&T格式的。 Linux 0.11 中文注释版 Linux 0.11 源码,基于《Linux内核完全注释》赵炯 1 asm.s 文件 我们先假设该文件处理的中断是无特权过渡的情况…

【精华文】C语言结构体特殊情况分析:结构体指针 / 基本数据类型指针,指向其他结构体

参考链接:Structure pointer pointing to different structure instance 注:可以查看此篇的问题和唯一的回复,那是相对正确的,不要看comment,有很多错误。 我是拒绝分析这种问题的,因为似乎没有人会这么乱用…

enum in c language

今天说说C语言中的枚举。 参考:Enumeration (or enum) in C 1 定义 定义一个枚举类型很容易: enum aa { a1, a2, a3 };这里 enum是关键字aa是枚举变量,也就是我们自定义类型a1,a2,a3是枚举成员 然后怎么使用呢? 首先&#…

信号量SIGCHLD的使用,如何让父进程得知子进程执行结束,如何让父进程区分多个子进程的结束

本教程基于 Ubuntu 20.10 gcc 10.2.0. 示例程序如果不能正常编译和执行,说明您系统和工具版本与我的不匹配,请自行查阅资料。 0 概述 先给出该信号的描述: SignalValueDescriptionSIGCHLD17Child status has changed (POSIX). Signal sent …

UNIX哲学

参考: 对比Linux与Windows 使用Linux想要做某些事情的时候,就拆开想,想想我需要哪些功能,需要哪些工具,依次怎么执行,然后用管道建立连接,让数据依次流过不同的工具,从而得到最终结果…

fork创建多个子进程

references: [1] how to create two processes from a single Parent [2] fork() in C [3] linux中fork同时创建多个子进程的方法 fork的本质,就是复制,把当前进程复制一份,然后两个进程并发地执行fork后面的语句,区别就是&#x…

wait系统调用

reference:Wait System Call in C 只强调几点,剩下的直接看参考链接内容就好了,不是偷懒,而是里面内容写的很好了,没必要再写一遍了,这种东西就是单纯的系统调用而已,理解了功能,就完事了&#…

正则表达式特别需要注意的点:“空“字符的匹配

在正则表达式中,[...]代表1个字符,不管里面有多少字符,最终这个东西的结果都是1个字符。 对于表达式[^a]表达的匹配除了a之外的字符,并且是1个字符。 需要注意的是,有些特殊字符是不会被匹配的。 我们看一个示例&am…

vim多列操作--插入/删除

插入 How to insert text at beginning of a multi-line selection in vi/VimVim Commands 删除 ctrl v使用上下左右键选中一片区域按d删除

vim进行行内某部分的复制剪切粘贴

ctrl v使用方向键选中你要复制的部分 按d(剪切)或者按y(复制)再移动到你的目标位置,按p粘贴(在正常模式下才行,如果不是,先按esc) 这个过程与你操作word文档的复制粘贴…

函数调用堆栈

基于孟宁老师的Linux内核分析 1 int g(int x){ 2 int y x 3;3 return y;4 }5 6 int f(int x){7 int z x 10;8 return g(z);9 }10 11 int main(){12 int a f(8) 1;13 return 0;14…

Vivado提高综合和实现的速度

让计算机的资源尽可能给vivado,综合、实现的时候修改一个参数 jobs改为你的计算机的最大值,我的计算机是12核的。 速度会快很多!

安装Ubuntu RISC V toolchain失败(网速、git配置原因)

git获取大容量工程出错:RPC failed; curl GnuTLS recv error : Decryption has failed. error: RPC failed; curl 56 GnuTLS recv error (-54): Error in the pull function.fatal: The remote end 官方GitHub仓库 gitee镜像仓库 如果网速不够&#xff0…

VirtualBox Ubuntu个人配置

注意这里VT-x启用,除了在BIOS启用CPU虚拟化,还得在命令行设置一次才可以勾选。 F:\>cd F:\VirtualBox # 进入VirtualBox安装目录F:\VirtualBox>VBoxManage.exe list vms # 查找所有虚拟机 "rhel64" {240f96d8-6535-431d-892e-b70f3dc4…

Ubuntu停止维护版本的软件源配置和系统升级方法

这里以Ubuntu 20.10版本为例(当前是2022.2.14,该版本已经停止维护),我们现在需要正常使用该版本,并且期待升级到21.10版本,我们需要 配置正确是软件源升级该版本 配置正确的软件源 配置国内镜像源 我们…

diff and colordiff on Ubuntu

在Ubuntu中使用diff来对比文件差异,但是不是很好用,尤其是着色方面,用起来很麻烦,因此可以安装colordiff。 我们有两个文件file1和file2,使用命令 colordiff file1 file2 -y -B -W 140就可以对比文件差异&#xff0c…

帮助你成为高手的视频和资料

1. 为什么大多数人不会真正成功 博客链接 视频链接 2. TED演讲:真正拉开你与周围人之家差距的,是自学能力 视频链接 3 埃隆马斯克:第一性原理,少用类比,类比多了就不能抓住本质了 4 如何成为一个顶尖高手 文章链…

【数据结构】快速排序非递归算法及其改进

在学数据结构中排序这一章节的时候,有一道有关快速排序的作业题描述如下: 按下述要求编写快速排序的非递归算法: 定义一个栈(或队列),把整个序列的上、下界入栈(或队列)。当栈&#…

【数据结构】对快速排序原理的理解(图解,通俗易懂)

学习数据结构时,书本上直接给出了快速排序的过程以及代码,对其原理解释的不够详细,琢磨代码后,发现其原理其实十分简单,简述如下: (1)在待排序列中找一个“中枢元素”(书…