9.2 中断向量表的结构

article/2025/9/13 7:40:23

计算机组成

9 中断和异常

9.2 中断向量表的结构

Screen Shot 2018-09-30 at 9.35.18 am

我现在已经知道了,在运算的时候 一旦遇到了异常情况,就翻到第一页的第一行开始写的这些操作的指示,开始往下执行。开始往下执行,这就能解决问题了。但是问题在于这段操作,解决的是我那个运算结果在空格里填不下的问题。可是我遇到新的问题应该怎么办呢?我们可能还会遇到很多的其他的问题。这个时候,这个手册的制造者实际上就需要做一些改进了。

手册的第一页不能只写一种解决情况。他要画一个表格,在这个表格里分了一二三四五条,填上不同的情况。我们遇到了不认识的操作符号,请看第一页的第二条;如果这个地方粘了一个虫子,然后你这个数字看不清楚了,请见第一页的第六条。这样我们就能解决不同的情况了。

Screen Shot 2018-09-30 at 9.35.28 am

那我们先来回顾UNIVAC对异常处理的方式。当算术运算溢出的时候,UNIVAC就转向地址0去取出指令。在那里会执行两条修复指令。这个处理方式已经是很灵活的了。只不过还有一些值得改进的地方。例如在存储器当中,如果从地址0开始只预留了两条指令的空间用于修复指令。那如果后来要改变修复的方式,需要再增加几条指令,这里预留的空间是否就有可能不够了。另外当需要处理的异常情况变多的时候,那就需要根据异常情况的不同,去执行不同的异常处理指令。如果遇到异常都只能转向地址0,就没有办法处理多种不同的异常了。因此,在这两个方面都需要进行改进。

那么就来看一看后来,8086是怎么做的?

Screen Shot 2018-09-30 at 9.35.36 am

8086是一个16位的CPU。它内部有四个16位的通用寄存器,对外则有16根数据线。但是它的地址线要更多一些,一共有20根。这样可以寻址的内存空间就是2的20次方,也就是一兆个Byte。

由于它内部的寄存器与运算器都是16位宽的,要生成20位宽的地址,就得用一定的转换方法。8086采用的是段加偏移的方式。

然后对于这一兆的空间不都是可以任意使用的,有两个区域保留作专门的用途。在这1M字节的内存空间中,最低的1K个字节保留作中断向量表区,而最高的十六个字节保留为初始化程序区。

Screen Shot 2018-09-30 at 9.35.45 am

我们结合图示来进行说明,这里用填充了颜色的方块用来表示这一兆字节的存储器。8086CPU复位之后,它第一次取指令的操作发出的地址是四个F一个0(FFFF0H)。这个地址就是在这一兆内存空间的最高的16个字节的这个地方。这个区域实际上是很小的,只能放很少的几条指令。通常放在这里的是一条无条件的转移指令,转移到内存空间当中的另一个地方。在那个地方存放着后续的系统程序。

那CPU复位之后,为什么不从全0(00000H)的地址开始取址呢?那样看起来岂不是更自然一些。那因为从0开始的地址空间也已经被占用了。这个1K(0000H~003FFH)的字节被用作中断向量表区,它一共存放了 256个中断向量,每个中断向量占四个字节。这样正好就是1K(256*4=\(2^{10}=1K\))个字节。除了这两块专用的区域,其他区域就可以用来存储一般的程序指令和数据。在这块区域(0000H~003FFH),还有那些用于进行中断处理的程序,这些程序就被称为中断服务程序。而这些程序代码起始地址则被称为中断服务程序的入口地址。

这就是中断向量的定义。

Screen Shot 2018-09-30 at 9.35.53 am

现在的CPU一般都能够处理多种不同的中断类型。

每个中断类型就对应一个中断向量,一共4个字节。在这四个字节当中,前两个字节(06H和30H)用于存放中断服务程序入口的偏移量,而且是低字节(06H)在前,高字节(30H)在后。因此,对于这个中断向量,这两个字节(06H和30H)就会被存放到指令指针寄存器(IP)当中去,而且前一个字节(06H)是寄存器当中的低字节,后一个字节(30H)是寄存器当中的高字节。那么中断向量当中的后两个字节(00H和40H),则对应了中断服务程序入口地址的段基值,用来存放到代码段寄存器,也就是CS寄存器。那么同样,前面那个字节(00H)对应了寄存器当中的低字节,后面的字节(40H)对应了寄存器当中的高字节。在8086当中或者是后来X86处理器的实模式下,就需要用CS和IP这一对寄存器来指定一个内存的地址。

Screen Shot 2018-09-30 at 9.36.02 am

这个地址的产生方式就叫做段加偏移。CS寄存器就是一个段寄存器,它是16位的。而刚才的IP寄存器则对应了偏移量,也是一个16位。这两个16位的地址就构成了逻辑地址。通常的表示方式就是用一个冒号分隔开这两个16位数(CS:IP)。那在CPU产生地址时,会将段寄存器(CS)当中的数左移4位,然后加上偏移量,这样加法运算的结就是20位的物理地址。这就是逻辑地址生成物理地址的方式。实际上是段基值乘以16加上偏移量,对于二进制来说左移四位就相当于乘以16了(二进制左移四位等价于十六进制左移一位)。

Screen Shot 2018-09-30 at 9.36.11 am

那基于这样的方式,每个中断向量都由两个段基值和两个向量的偏移地址组成。因为每一个中断向量占四个字节,在整个中断向量表中一共有256个中断向量,分别命名为0号、1号、一直到255号中断。这个中断向量表要在系统里面启动时进行初始化。假设1号向量的初始值是这样的,当cpu接收到中断时,如果发现时1号中断。因为各个中断向量放置的地址是固定的,那cpu不需要通过执行指令,直接通过硬件电路的设置,就可以发出内存访问来读取这四个字节的内容。然后将其中高两个字节送到CS寄存器当中去,低两个字节送到IP寄存器当中去。

对于8086来说,这两个寄存器(CS和IP)的功能就相当于我们在之前介绍处理器内部结构时提到的PC寄存器。所以,这两个寄存器的值一旦发生改变,下一个周期cpu就会从这个新的地址(CS:IP)开始取下一条指令,根据段加偏移的计算方法,cpu发出的地址就是43006。因此,也就是说在遇到1号中断时,cpu就会转到43006这个地址开始执行程序。当然,需要事先把1号中断的服务程序存放在这里(存储器内)。

与此类似,我们还会把0号中断的服务程序放在存储器的另一个地方,然后将0号中断程序的起始地址分解成段基值和偏移地址,存放在0号中断向量所在的位置。当cpu遇到中断时,如果发现是0号中断,则会将0号中断向量对应的内容取出,分别填到CS和IP寄存器当中去。这样cpu就会从0号中断服务程序的起始地址开始取出指令进行执行。

我们注意到,这些中断服务程序在内存当中的存放顺序并没有要求。并不需要按照中断类型的顺序,先放0号中断服务程序,再放1号中断服务程序,而是可以随意放置。只需要把它的起始地址存放在中断向量表的对应位置就可以了。这样做就比UNIVAC的方式要灵活的多,一来中断服务程序就可以可长可短,不用担心在从0开始的地址到底要预留多少的空间才够;二来中断服务程序的存放位置如果发生改变,也没有关系,不需要修改cpu的硬件设计,而只需要修改中断向量表中对应的中断向量就可以了。这样只用初始化好中断向量表,并在存储器当中准备好对应的中断服务程序,cpu在遇到中断时就可以自动的跳到对应的中断服务程序进行处理。

关于中断向量的相关的计算,我们来看几个简单的练习。

Screen Shot 2018-09-30 at 9.36.19 am

第一,如果中断类型码,也就叫做中断类型号为20H。那中断向量起始的逻辑地址应该是什么呢?首先,我们知道中断向量表是从地址0开始的,一共256个中断向量顺序存放,而每个中断向量占四个字节。所以,中断向量存放的位置就是它的中断类型号乘以4,那这个中断地址就是0000:0080。如果这个中断向量中四个字节的内容分别是10H、20H、30H和40H,那中断服务程序的入口地址应该是什么呢?

按我们刚才介绍的情况。这四个字节单元低两个字节对应了IP寄存器,高两个字节对应了CS寄存器。而且地址较低的这个字节是放在寄存器当中较低的位置。所以,这中断服务程序的入口地址应该是4030:2010。这两个练习就是说明了cpu在遇到了中断之后,硬件完成的工作。如果cpu现在遇到的中断类型号是20H,则会通过硬件进行乘4的操作,从而得到这个逻辑地址(0000:0080)。然后将这个逻辑地址发到存储器中,读回了这四个字节(10H、20H、30H 和 40H)的内容。然后,按照我们刚才规定的原则拼接出了这样两个16位数(4030:2010),并且把这两个16位数分别存放到CS和IP寄存器当中去。这样在下一个时钟周期就会将新的地址发送到存储器去取下一条指令了。

然后我们再来看另一个练习。

Screen Shot 2018-09-30 at 9.36.28 am

如果我们现在要为17H号中断新写了一段中断服务程序,而且把这段中断服务程序放到了存储器的某一个地方,地址是2340H:7890H。

那现在我们就需要去更新中断向量表。现在问题就是,我们要更新中断向量表中的哪四个字节?而且更新成什么样的内容?那我们可以一起来算一下。因为中断类型号是17H,那对应中断向量的地址就应该是它乘以4(17*4 = 5C (mod 16))。由这个地址(0000:005C)开始,向高地址增长,一共4个字节。所以,这四个字节的逻辑地址是这样的(第一个空)。

这四个字节单元当中分别应该填写什么样的内容呢?那么还是要记住这个原则,如果把这个逻辑地址(2340:7890H)从右往左看。最右边的这个字节(90H)放在最低的地址,而最左边的这个字节(23H)放在最高的地址。这四个字节依次排放。所以,地址由低到高四个字节内容分别应该是90、78、40和23。

那这两个练习就分别展示了cpu硬件查找中断向量表的过程,和准备好中断服务程序去初始化或者修改中断向量表的过程。

Screen Shot 2018-09-30 at 9.36.36 am

对于8086的中断向量表cpu已经固定使用了前五个类型的中断,具体的功能我们后面会再介绍。之后的27个中断(5~31)也是保留给后续的cpu使用的。而除了前20个中断,之后的224个的中断则是交给使用cpu的用户自行定义。

Screen Shot 2018-09-30 at 9.36.45 am

我们现在知道了,原来我们的第一页制造者给我们列了一张表格。一共有256条。那我们在遇到异常情况的时候,就可以根据事先的约定对应不同的情况,去找对应的那一条表项。那条表项实际上是指一个页码。比如说第四条说翻到第十二页,这第十二页翻过来以后,写了具体的操作,我们应该做什么事情,操作还挺复杂,写了好几页,我们都放在一页纸是放不下的。所以,这就是我们现在要怎么处理异常情况的方法。

随着我们要做的运算任务的增加,这个表的内容可能还需要进一步的扩展。接下来我们就来看一看它是怎么扩展的。

转载于:https://www.cnblogs.com/houhaibushihai/p/9742806.html


http://chatgpt.dhexx.cn/article/vvd5OHcd.shtml

相关文章

中断向量表的重印射

基于HAL库 以STM30F303RBT6为例: 打开system_stm32f3xx.c文件,修改其中的中断向量表位置,修改flash offset即可。 下载的位置也,也需要修改 做远程升级时,需要在单片机启动前运行一个boo程序,在boot程序中…

嵌入式杂谈之中断向量表

虽说接触了好久的单片机或者说嵌入式开发,不过对于有些概念还是比较模糊,因此此系列将会从一些零碎的小知识点出发,慢慢的遍历整张嵌入式开发的地图。 这次先来看一下中断向量表。 至于为什么会提到中断向量表,主要是因为我自己…

中断向量表--

中断向量表如何确定中断的入口地址? 每个中断对应一个中断号,比如一个中断事件的中断号为0x00,那么它对应的中断程序的入口地址就是0x0000-0x0003,另一个中断事件的中断号为0x01,那么它对应的中断程序的入口地址就是0…

一文了解Cortex-M中断向量表对齐原则

关注星标公众号,不错过精彩内容 来源 | 痞子衡嵌入式 一、Cortex-M中断向量表对齐原则 中断向量表就是一个集中保存系统全部中断处理函数(xxxIRQHandler)地址的常量数组(函数地址要占 4 个字节,因此数组中每个元素大小…

STM32中断向量表复制到SRAM中运行

1、生成Map文件 复制中断向量表前需要知道中断向量表的大小,可以通过编译生成的Map文件查看。 2、查看中断向量表大小 中断向量表的大小是固定的,与程序代码量无关,打开Map文件,直接搜索0x08000000,我使用的 MCU 是…

通过GDK8观察ARM框架下的中断向量表

一、中断向量表介绍 中断是指计算机运行过程中,出现某些意外情况需主机干预时,机器能自动停止正在运行的程序并转入处理新情况的程序,处理完毕后又返回原被暂停的程序继续运行。 以上是中断在百度百科中些较为浅显的解释,中断实际…

【STM32】中断向量表

我是通过这个进行学习的,我觉得讲的很好,这里我稍加修改,作为自己的学习笔记: 嵌入式杂谈之中断向量表 前言 STM32根据boot引脚的配置方式有3种启动方式,但是无论哪一种方式,对于STM32来说都是从0x0000 0000启动 ST…

Cortex M4 中断向量表

前言 重新学习Cortex M4的中断向量表内容。中断向量表是Cortex M4自带的功能,厂家可以根据需要自行定义,所以需要学习该内容,直接看Cortex M4内核相关即可。我这查看的是《Cortex M3与M4权威指南.pdf》。 一、中断向量 中断向量是什么&…

中断向量表

关于中断向量的几点注释 1. 系统引导时,中断向量表放在内存何处? 系统刚引导时,内存0x00000到0x0003FF共1KB的空间用于存放中断向量表。每个中断向量占用4个字节,共可存储256个中断向量。 2. 系统引导时,处在实模式下,只可寻址1MB,为什么要用4个字节来寻址中断呢处理程…

TF_REPEATED_DATA ignoring data with redundant timestamp for frame left_wheel at time

使用urdf和xacro编写机器人仿真模型的时候,同时开启gazebo和rviz的时候遇到的问题 ubuntu20.04 ros noetic 开启gazebo并启动rviz时,rviz终端会一直产生一个警告:TF_REPEATED_DATA ignoring data with redundant timestamp for frame left…

ProtoBuf(Google Protocol Buffers)—— repeated 修饰字段注意点(packed修饰)

ProtoBuf—— (repeated 修饰 ) repeated1、定义2、使用事项 参考 repeated 1、定义 repeated类型相当于STL的vector,可以用来存放N个相同类型的内容。proto2 中还有 repeated 可选,在proto3 中则已经被摒弃并且默认格式为pack。…

Responder

在hack the box 最后一个sql注入题时,有这个工具的使用,之前没有接触过,看write up上是需要利用两个IP地址,似乎与内网渗透有关,马上查找相关资料,看到底是个什么东东。 什么是Responder 在攻防领域&…

Reverse

IDA中文不显示解决 参考链接 VScode中文乱码解决参考链接 (1 ~ 10攻防世界)(11~20为Buu,近乎为shift F12查找字符串) 1. xxxorrr 题目链接 题目WP 心得:可能会有其它隐藏函数对所需结果进行操作 2. SignIn RSA算法介绍 c是密文,m是明文…

java中@Repeatable的理解

Repeatable是jdk8中新增的注解,使用如Spring中的ComponentScan注解。在没有Repeatable注解的的注解中,在同一个地方使用相同的注解会报错,有了此元注解注解的注解,就可以在同一个地方使用相同的注解。其官方文档如下 The annotati…

TS:解决docker无法启动,报:start request repeated too quickly for docker.service错误-2021.12.08(已解决)

目录 文章目录 目录1、报错现象2、解决办法3、总结关于我最后 1、报错现象 首先,我当前的环境是:docker 20.10.11,vmworkstation虚机 很奇怪,自己的docker用着用着就出现问题了,查看服务发现起不来,重启docker服务也…

【已解决】TF_REPEATED_DATA ignoring data with redundant timestamp for frame

目录 1 问题背景2 问题探索3 问题解决4 告别Bug 1 问题背景 环境:Ubuntu20.04 ROS-noetic 现象:打开Rviz与Gazebo加载机器人模型时,终端不停刷新警告TF_REPEATED_DATA ignoring data with redundant timestamp for frame,且在未施…

已解决(一分钟)TF_REPEATED_DATA ignoring data with redundant timestamp for frame base_footprint at time解决方案

<1>问题描述 前言-仿真实验需求&#xff1a;获取小车的全局坐标系下的位姿信息&#xff0c;因此使用gmapping建图&#xff0c;并使用地图服务调用发布&#xff0c;自己写了个节点将map坐标系添加到现有的TF树上&#xff0c;最终TF树见最后截图。 进入正题&#xff0c;想…

【Protocol Buffer】Protocol Buffer入门教程(五):repeated限定修饰符

00. 目录 文章目录 00. 目录01. 限定修饰符介绍02. 字段API分析03. 测试代码04. 编译和测试05. 参考 01. 限定修饰符介绍 repeated 代表可重复&#xff0c;我们可以理解为数组 syntax "proto3";//指定版本信息&#xff0c;不指定会报错message Person //message为…

protobuf入门教程(四):repeated限定修饰符

限定修饰符说明 repeated 代表可重复&#xff0c;我们可以理解为数组&#xff1a; syntax "proto3";//指定版本信息&#xff0c;不指定会报错message Person //message为关键字&#xff0c;作用为定义一种消息类型 {string name 1; //姓名int32 id 2; …

一个真·菜鸟理解的springmvc工作原理

1 springmvc的映射器和适配器 1.1springmvc的映射器 根据客户端请求的url&#xff0c;找到处理本次请求的handler&#xff08;处理器&#xff09;&#xff0c;将url和controller关联起来 1.2springmvc的适配器 对映射器查找到的controller中的方法进行调用。 第一种&#xff1…