计组第八章 CPU 的结构和功能
第八章 CPU 的结构和功能
- 高级语言编写的程序,必须经过编译程序和汇编程序的编译和汇编之后,形成机器语言程序。
- 指令系统是计算机软硬件的结合面
- 这一章分析机器语言指令如何在CPU硬件上运行
8.1 CPU的结构
我们先介绍CPU的功能,然后讨论什么样的结构能够对实现这个功能
8.1.1. CPU的功能
(1) 控制器的功能
功能 | 说明 |
---|---|
取指令 | 将指令从内存中取出 |
分析指令 | 解析指令的操作码,分析这条指令完成什么功能,是指令集的哪一种功能 |
执行指令 | 控制器发出相应的操作命令,控制响应的操作部件完成功能,这些控制命令有一定的顺序 |
控制程序输入及结果的输出 | 第五章说过 |
总线管理 | 管理总线的使用权 |
处理异常情况和特殊请求 |
(2) 运算器的功能
第六章就是讲的这个
我们来总结一下CPU的功能
功能 | 说明 |
---|---|
指令控制 | 取指令,分析指令,执行指令 |
操作控制 | 执行指令,控制输入输出等 |
时间控制 | 控制一个指令的操作命令的顺序等 |
处理中断 | 处理异常情况和特殊请求 |
数据加工 | 运算器的功能 |
8.1.2. CPU的结构框图
- 先看CPU的外部结构
线 | 方向 | 向外 | 向内 |
---|---|---|---|
控制总线 | 双向 | CPU向外器件发出的命令 | 外设的请求以及状态 |
数据总线 | 双向 | CPU输出 | CPU输入 |
地址总线 | 向外 | CPU向内存或者外设接口发出地址 |
结构 | 任务 |
---|---|
寄存器 PC IR | 指令控制,PC保存指令地址,IR是指令寄存器 |
CU时序电路 | 操作控制,时间控制,就是控制指令的顺序的 |
ALU寄存器 | 数据加工 |
中断系统 | 处理中断 |
这个是内部结构的结构,有些部分已经介绍过了,一些部分下面做专门介绍
8.1.3. CPU的组成部分
(1) CPU的寄存器
不同的CPU,不同的指令集,寄存器的设置是不一样的,因此这里的仅仅是一个抽象的讲解,主要讲寄存器在各种CPU中的分类
① 用户可见寄存器
用户在编写程序的时候,用户可以使用
还有用户不可见寄存器,比如说流水段之间的流水段寄存器都是用户不可见的
寄存器种类 | 功能 | 说明 |
---|---|---|
通用寄存器 | 存放操作数 | 可作 某种寻址方式所需的 专用寄存器,支撑某种寄存器 |
数据寄存器 | 存放操作数(满足各种数据类型) | 有的寄存器可以两个寄存器拼接存放双倍字长数据,比如ACC与M |
地址寄存器 | 存放地址 | 比如8086里面的段寄存器 其位数应满足最大的地址范围 用于特殊的寻址方式 段基值 栈指针 |
条件码寄存器 | 存放条件码 | 可作程序分支的依据 如 正、负、零、溢出、进位等 |
② 控制和状态寄存器
a. 控制寄存器
比如CPU从内存当中取一条指令
PC ——> MAR(主存地址寄存器)——>M(主存) ——> MDR(主存数据寄存器) ——> IR
这些都是控制CPU操作的,因此是控制寄存器
其中:
- MAR,MDR,IR是用户不可见的
- PC是用户可见的,用户在编写程序的时候,用户可以使用
MAR 和MDR都是在CPU中的
b. 状态寄存器
比如说上面的条件码寄存器 存放条件码
还有PSW(程序 状态 字)寄存器,存放程序状态字
程序状态字
当发生中断的时候,程序会跳转到处理程序,这时需要保存程序的断点和运行现场
在这些断点和运行现场中,包括软件信息和硬件信息,有些保存程序状态的寄存器,可以通过指令集中的指令进行读写,有的没法
因为涉及到的状态比较多,如果为每一个状态都设计一个指令进行读的话,指令集会变大,为了完成现场和断点的保存,就将软硬件状态的寄存器集合成了一个大的寄存器,这就是程序状态字寄存器
字长比较长,有的达到几千位,可以通过交换程序状态字的方式来恢复现场
(2) 控制单元CU和中断系统
① CU
解析指令之后,产生该指令的微操作命令序列
不仅仅要产生操作命令,而且要保证先后顺序
CU的设计有两种方法
方式 | 逻辑 | 说明 |
---|---|---|
组合逻辑设计 | 硬连线逻辑 | 完全由硬件组成,速度快,适合RISC计算机 |
微程序设计 | 存储逻辑 | 设计简单,适用于CISC |
② 中断系统
在后面会具体讲解
(3) ALU
在第六章的时候具体讲解过了
8.2 指令周期
这个就是讲解指令的执行过程的,为第九章,第十章做基础
8.2.1. 指令周期的基本概念
(1) 指令周期
取出并执行一条指令所需的全部时间
也可以说是解释一条指令,解释就包括了取址分析执行
下面是完成一条指令的方法
仅仅是这里这么讲,不同的CPU分发是不一样的,具体情况具体分析
如果这样分的话,指令周期这么划分
(2) 每条指令的指令周期不同
即使在同一个CPU中,不同指令的指令周期也是不同的
图示 | 说明 | 例子 |
---|---|---|
![]() |
只有取指周期 | 8P(空操作),计算机不需要做任何操作 |
![]() |
取指周期和执行周期时间长度相同 | ADD mem,从内存单元中取出一个操作数,和ACC做加法,结果保存在ACC中 取值是将指令取出送到CPU中,执行也是将数据取出送到CPU中,时间基本相同,大部分时间都是取 |
![]() |
取值和执行时间不一致 | MUL men,这个和上面一样做乘法,但是执行乘法的时间是比加法多的 |
(3) 具有间接寻址的指令周期
我们来回顾一下间接寻址的示意图
就是操作数的地址还在主存中,还需要取一次
下面是指令周期的分段
- 在第七章中有很多寻址方式,其中间址寻址方式在寻找操作数地址的过程中,也要访问存储器,如果放在执行周期的话,执行周期可能有两次访存,导致执行周期变长
- 因此在取址和执行周期之间专门加一个间址周期,取操作数的地址,执行周期只是取操作数
(4) 带有中断周期的指令周期
中断周期:
- 在执行结束的时候确定是否有中断请求
- 如果有,需要响应中断,比如保存现场,硬件关中断等
如果有中断机制的话,就是这四段
后面讲的两种指令是一个指令集中都存在的,只是某些指令有间址周期,某些有中断周期
(5) 指令周期流程
假设指令集中的周期都有四个阶段
这个图仅仅是完成一条指令
(6) CPU 工作周期的标志
指令周期的不同阶段,控制器要做不同的操作,因此控制器在指令周期不同阶段要发出不同的命令,控制器要知道在哪个阶段,即使是操作同一个部件,指令可能也不同
CPU访存有四种性质
这是CPU访问内存的分类
周期 | 操作 |
---|---|
取指周期 | 取指令,保存到IR中 |
间址周期 | 取地址,保存到IR或者MDR的地址码部分 |
执行周期 | 存取操作数或结果,保存到CPU的寄存器或者内存中 |
中断周期 | 存程序断点 |
可以看到,这些操作的起始终止点都不同,控制器要根据所处的阶段发出命令,因此控制器得知道处于哪个阶段
很简单,就是用D触发器对四个阶段进行标识
- FE就是取值,IND就是间址,EX就是执行,INT就是中断
8.2.2. 指令周期的数据流
我们先来列出CPU响应的结构
(1) 取指周期数据流
下面是说明
图示 | 说明 |
---|---|
![]() |
PC->MAR->地址总线->存储器 CPU将指令地址传给存储器 |
![]() |
取操作第一步: CU将操作命令通过控制总线传给存储器,让存储器进行取址 |
![]() |
取操作第二部: 存储器取出指令之后通过数据总线发送到MDR,然后送到IR,这个时候指令已经被送到了CPU, |
![]() |
为取下一条指令做准备,如果没有跳转指令的话,PC+1,这个是CU控制完成的 |
(2) 间址周期的数据流
这是间接寻址的方式,操作数的地址在主存当中,间址周期就是要取出操作数的地址
起始操作可以从IR开始,也可以从MDR开始,我们假设从MDR开始,也就是我们要取的操作数的地址所在的内存单元的地址保存在MDR 当中
示意图 | 说明 |
---|---|
![]() |
将存操作数所在的地址的内存单元的地址送给存储器 |
![]() |
CU发出读操作给存储器,让存储器根据地址进行读操作 |
![]() |
存储器将取出的 操作数的地址 送到MDR当中,此时MDR的地址码部分就是操作数的地址 |
(3) 执行周期数据流
不同指令的执行周期数据流不同 ,这节不做介绍,第九章具体介绍
(4) 中断周期数据流
先看中断周期需要的组成结构
中断周期做了三件事
- 保存断点
- 形成中断服务程序的入口
- 硬件关中断
这里给出前两部分的示意图
阶段 | 示意图 | 说明 |
---|---|---|
保存断点:就是将断点写入到存储器中 | ![]() |
保存程序断点,也就是将程序断点保存到某一个内存单元当中,要知道内存单元的地址,在这个结构上,由CU确定将断点保存到哪一个内存单元地址中 保存断点一:CU将地址送给存储器 |
![]() |
这是一个写操作,CU发出写命令给存储器 | |
![]() |
断点:就是中断之后要返回的程序的位置,也就是中断后执行的下一条指令的地址,这个值保存在PC当中 保存断点二:PC->MDR->存储器,将断点存进去 |
|
形成中断服务程序的入口地址 | ![]() |
具体如何形成在后面会介绍,这里只需知道入口地址是CU给出的,CU写出的值直接送给PC,然后PC就保存了中断服务程序的地址,下面执行中断服务程序 |
8.3 指令流水
流水线技术是现代处理器最常用,最有效地提高指令解释速度的方法,从结构功能简单的嵌入式处理器,到复杂的高性能处理器,都使用了流水线技术
目的:提高指令解释速度
解释就包括取指令,分析和执行
8.3.1. 如何提高机器速度
我们先来回顾一下如何提高机器速度
计算机由多个部件组成,要提高计算机的速度就要提高各个部件的速度
方法 | 举例 |
---|---|
提高访存速度 | 1. 使用高速,高性能的芯片 |
2. 使用Cache,把最常用的数据和指令放到Cache中,CPU可以通过访问Cache来访问这些数据 | |
3. 多体并行,对多个存储体进行交叉访问;在一个主存周期当中,有多个存储体向CPU提供数据或者CPU可以访问多个存储体 | |
提高 I/O 和主机之间的传送速度 | 最开始IO和主机之间进行数据传送的方式是程序控制方式,CPU和外部设备不能并行工作,是串行工作的,CPU和总线的利用率较低 |
1. 为了解决这个问题,采用中断方式,CPU和外设可以在部分时间并行工作,提高了CPU的使用率 | |
2. DMA DMA控制器直接在内存和外设之间进行数据传输,提高CPU使用率 | |
3. 通道 I/O处理机 在IO处理机下,整个数据传输过程,数据校验过程完全由IO处理机完成 | |
4. 多总线方式 | |
提高运算器速度 | 1. 高速芯片 2. 改进算法 3. 快速进位链 |
提高整个处理机处理能力 | 1. 高速器件 |
2. 改进系统结构 ,开发系统的并行性 |
改进系统结构 ,开发系统的并行性这是下面主要讲解的
8.3.2. 系统的并行性
(1) 并行的概念
并行有两个概念
-
并发:两个或两个以上事件在 同一时间段 发生
比如在操作系统中的分时操作系统,将时间段分成小的时间片,多个程序交替进行,对应用户来说,就是同一时间段多个程序同时运行
-
同时:两个或两个以上事件在 同一时刻 发生
这个是真正地同时进行,时间上相互重叠
这是并行的两种方式(要实现并行就用这两种方式),流水线就是同时方式的一种
(2) 并行性的等级
也就是并行性的单位是什么
等级 | 发生对象 | 说明 | 程度 | 实现 |
---|---|---|---|---|
过程级 | 程序、进程 | 就是两个程序或者进程同时进行 | 粗粒度 | 软件实现(比如操作系统实现) |
指令级 | 指令之间,指令内部 | 也叫ILT(instruction level t是并行的意思),也就是多条指令同时进行解释或者执行;也可以是一条指令内部的微操作之间同时进行 | 细粒度 | 硬件实现 |
这个要注意了,好好思索一番
8.3.3. 指令流水原理
我们假设后面的指令只有取值和执行两个阶段,仅仅是为了讲解方便
(1) 指令的串行执行
如果将取指令的部件和执行指令的部件完全独立开来的话,这就是为什么CU要知道处于什么阶段,处于什么阶段就会操作什么部件
取值 执行 的部件在上面已经讲过了,就是各个阶段的数据流
- 取指令 取指令部件 完成
- 执行指令 执行指令部件 完成
- 总有一个部件 空闲
(2) 指令的二级流水
- 若 取指 和 执行 阶段时间上 完全重叠
- 指令周期 减半 速度提高 1 倍
这里理想情况下提高一倍,实际上,流水线一直处于满负荷的情况下是很难的
(3) 影响指令流水效率加倍的因素及解决方法
这里采用二级流水为例
① 执行时间 > 取指时间
比如说MUL mem,这个执行 > 取值,总之复杂的指令可能是这样的
解决方法
取指令和执行指令的部件之间,加上一个缓冲区,用户缓冲取址部件取回来的指令
- 如果取指部件速度较快,那么取出来的指令可以先放到缓冲区中
- 一旦执行指令部件空闲了,就可以从缓冲区中拿出指令来使用
② 条件转移指令对指令流水的影响
条件转移就是进行条件判断之后转移
对于无条件转移,对于指令流水比较小,在译码阶段就知道转移到哪一条地址
条件转移必须等 上条 指令执行结束(得到判断条件后),才能确定 下条 指令的地址
现代机器语言中,条件转移指令是比较多的
解决办法
就是猜测法,比如说分支预测,这不是这节课的方法,这里不做说明,可以自己将查阅
(4) 指令的六级流水
将指令分为六个阶段
符号 | 操作 |
---|---|
FI | 取指令 |
DI | 指令译码 |
CO | 形成操作数地址 |
FO | 取操作数 |
EI | 执行指令 |
WO | 结果写回 |
假设每一段的时间都是一样的,都是一个时间单位
- 串行执行:54个时间单位
- 六级流水:14个时间单位
这里是假设指令不存在冲突或者没有转移指令
8.3.4. 影响指令流水线性能的因素
(1) 结构相关—部件冲突
不同指令争用同一功能部件产生资源冲突,比如说一条指令在使用ALU计算下一条指令的地址,另一条指令使用ALU执行操作
- FO,FI,WO这三个操作都是要使用内存的
- 第四个时间段,指令1和指令4同时使用内存,第6个时间段,指令1,3,6同时使用内存,这都会发生冲突,降低流水线性能
解决方法
-
停顿/加入气泡
加入指令1 4在第四个周期同时使用内存,那么指令4可以先停一停,第五个周期或者更后面再取指令
-
指令存储器和数据存储器分开
取指令从指令存储器操作,取操作数的时候,对数据操作器操作
按照冯诺依曼结构,指令和数据是地位相同的
但是现代计算机中,将指令Cache和数据Cache分开,就是为了解决冲突问题
-
指令预取技术(适用于访存周期短的情况)
取指部件利用空闲时间取出多条指令,放入CPU的指令缓冲队列,等待执行
这里仅仅是以存储器冲突为例,其他部件也会冲突;寄存器,运算器也可能会发生冲突
(2) 数据相关
不同指令因重叠操作,可能改变操作数的 读/写 访问顺序
就是说,不同指令因重叠操作,流水线可能分成多个段,可能是多个读段或者多个写段,通常情况下,前段是读,后段是写操作,可能改变操作数的读写次序
通俗地说,就是一个寄存器或者内存存储单元,本来应该先写后读,但是写是需要时间的,比如说写之前要先计算结果,然后结果还没出现呢,另一个指令就直接读走了结果
总共有三种数据相关
-
(先)写后读相关(RAW,read after write)
就是对一个存储单元(内存的存储单元或者是寄存器)先写后读
-
读后写相关(WAR)
-
写后写相关(WAW)
我们来举个例子
相关类型 | 指令说明 | 说明 | 出现相关的可能 |
---|---|---|---|
写后读相关 | SUB R1,R2,R3;((R2) - (R3) —> R1) ADD R4,R5,R1;((R2) - (R3) —> R1) |
就是先进行减操作,结果保存在R1中,然后利用R1中保存的结果执行加操作 正确执行的话必须第一条指令先执行,然后执行第二条指令 |
可能减法的结果还没有出来,加法就已经进行了,导致顺序冲突 |
读后写相关 | STA M,R2 ;((R2) —> M 存储单元) ADD R2,R4,R5 ;((R4) + (R5) —> R2) |
先将R2的值保存到M中,然后将加法的结果保存到R2中 | 可能加法先执行,得到R2的结果,然后STA指令的取值时间比较慢,最终加法的结果存到M中了? |
写后写相关 | MUL R3,R2,R1 SUB R3,R4,R5 |
先将 R1 × R2的结果保存在R3中,然后将 R4 - R5的结果保存在R3中 最终R3的结果应该是减法指令的结果 |
乘法的执行时间比较长,可能减法先计算出结果,然后乘法再计算出,最终结果保存的是乘法的结果 |
读后读相关,没啥冲突的,直接读就行了,不需要更改的
解决办法
这是体系结构的只是,这里仅仅是点一下
以 ① SUB R1,R2,R3;② ADD R4,R5,R1为例
-
后推法
比如说①的结果还没计算出来呢,②先等等,等到1结果出来再说
-
采用 旁路技术,也叫相关专用通路,也叫前向通道
后推法会浪费时间,因为必须要等到 计算结果 写入到 R1后才能读,浪费的时间就是 计算结果写入到R1的时间
事实上,R1中保存的数值,也就是②中需要的R1的值,在①的执行阶段,减法操作结束后,在运算器的输出端就给出了,不必等到输入到R1再使用
旁路技术不需要等待写的结果,直接当运算器的输出端输出结果的时候,直接送到②中运算器的输入端
(3) 控制相关
前面一种是资源引发的,一种是数据引发的,控制相关是转移指令引发的
下面举个例子,间接寻址求平均数
BNE 指令必须等 CPX 指令的结果 才能判断出 是转移 还是顺序执行
这有什么问题呢?
-
假设指令3就是一条条件转移指令
-
只有3的执行阶段EI结束的时候,才知道要不要转移
如果不成立,顺序执行,如果成立,要给出新的地址
-
图中指令3由于还没执行结束,指令4 5 6就依次开始取指令并且开始执行了了
-
但是指令3结束的时候,如果要跳转到指令15,那么中间的指令就不应该进行,他们的执行结果要作废,这就是转移损失
8.3.5. 流水线的性能
知道流水线的性能指标,进行分析进而设计好的,高性能的流水线
(1) 吞吐率 Tp
单位时间内 流水线所完成指令 或 输出结果 的 数量(如果只是普通流水线而不是指令流水线的话,看到就是输出结果的数量)
这里有两个指标
设 m 段的流水线各段时间为Δt,就是流水线一共被分成了m段,每一段的时间相同
指标 | 说明 | 计算 | 计算说明 |
---|---|---|---|
最大吞吐率 | 流水线满负荷运载,没有发生结构,数据,控制相关,这条流水线达到的最大吞吐率 | ![]() |
每经过一个Δt就会有一个结果输出,理想情况下是不中断的 |
实际吞吐率 | 完成任务的条数 / 所需的时间 | 连续处理 n 条指令的吞吐率为![]() |
m ·Δt + (n-1) · Δt 这个时间是一开始的指令有mΔt,后面有n-1个指令,每经过一个Δt就会有一条指令输出 |
最直接的方法就是计算某一段时间内执行了多少条指令
(2) 加速比 Sp
采用流水线技术和不采用流水线技术的速度比值
这种指标不一定只用在流水线当中,任何加速方法都可以用这个指标的
也可以是时间比值的倒数,没有采用流水线的时间 / 采用流水线的时间
- 设流水线各段时间为 Δt
- 完成 n 条指令在 m 段流水线上共需 T = m · Δt + (n-1) · Δt
- 完成 n 条指令在等效的非流水线上共需 T' = nm·Δt
(3) 效率
流水线的效率:就是流水线中硬件的使用率
这里有流水线的两个概念
-
建立时间:第一条指令从开始到结束的时间
图中可以很形象地看出,这段时间之后,流水线才真正建立起来
-
排空时间:最后一条指令从开始到结束的时间
-
由于流水线有 建立时间 和 排空时间,因此各功能段的 设备不可能 一直 处于 工作 状态
比如t1时间段,只有S1在运行,S2-S4都是空闲的
流水率 = 流水线中各功能段的 利用率
就是矩形的面积 / 非空白的面积
可以看出效率与执行指令的条数是有关的
8.3.6. 流水线的多发技术
之前讲解了用流水线提高指令的解释速度,这节是在流水线的基础上,进一步提高速度的方法
用一条流水线可以提高指令的解释速度,如果用多条流水线,就是多条指令同时进入多条流水线当中,速度可以被进一步提高
这是一条流水线
(1) 超标量技术
- 在每一个时钟周期之内,有多条独立的指令,进入到不同的流水线当中去执行
- 这就要为多条流水线配置多个功能部件
下图以三条流水线为例
- 每个时钟周期,分别有三条独立的指令分别进入每一个流水线执行
- 这样的话,指令的最高加速比可以比一条提升三倍
不能调整 指令的 执行顺序,通过编译优化技术,把可并行执行的独立的指令搭配起来
(2) 超流水线技术
- 在 一个时钟周期 内 再分段 ( 以3 段为例)
- 在一个时钟周期内 一个功能部件使用多次( 3 次)
-
即使是在一个时钟周期,里面也是需要多个部件的,比如取指令操作,需要PC,CU,MAR,MDR等部件
-
将这些部件再分段,一个部件使用结束之后,下一个指令过来使用
每个时钟周期分成三段,在每一个时间点都可以有一条指令进入
流水线速度是原来速度的 3 倍
这种方式与将流水线分成12段是不一样的
在流水线的设计方式中,流水段之间是要加入锁存器的,将每一个流水段的结果在锁存器之中进行锁存,作为下一个流水段执行的时候的操作信号,控制信号或者操作的数据
如果使用超流水线技术,那么在一个流水段之间的三份时间之间,是没有锁存器的
所以超流水线技术中,不同的指令,处在同一个流水段之中,相互之间的信号不能叠加
意思就是第一个指令在一个时钟段的第一块得到的结果,第二个指令不能在这个时钟段的第二块使用,只用到第二个时钟段,第一个指令的结果到了锁存器,第二个指令才能使用
现代计算机中,很多处理器都采用超流水技术
不能调整 指令的 执行顺序,靠编译程序解决优化问题
(3) 超长指令字技术
在数字信号处理,多媒体信号处理中,用的非常广泛
- 由编译程序 挖掘 出指令间 潜在 的 并行性,将 多条 能 并行操作 的指令组合成 一条具有 多个操作码字段 的 超长指令字(可达几百位,包括多个操作码字段,多个操作数字段)
- 这条指令被从计算机的内存中取出,多个操作码字段进行译码,多个并行的部件分别执行相应的操作
- 减少了取指时间,因为每次取出多条指令
灰色的部分是执行时间,执行部件有多个
- 取值阶段一次取一条超长指令字
- 然后译码阶段也是CU进行译码
- 在执行阶段,CU控制多个执行单元并行工作,因为编译程序已经认为这些指令是可以并行的,意思就是执行的时候不会冲突,比如说一个进行加减法,一个进行存取数等
- 然后第一个去完之后,下一个就能直接取指,一次执行的时候,执行一个超长指令字
- 特点就是 采用 多个处理部件
8.3.7. 流水线结构
(1) 指令流水线结构
完成一条指令分 6 段(实际上对不同结构的指令和机器是不一样的,这里是以6段为例), 每段需一个时钟周期
-
若 流水线不出现断流(也就是不产生资源 数字 控制冲突,并且指令条数足够,能够连续输入到流水线中) 1 个时钟周期出 1 结果(这个结果是一个指令的结果,不是一个指令在一个时钟周期的结果)
如果断流的话,要考虑建立时间和排空时间
-
不采用流水技术,6 个时钟周期出 1 结果
-
理想情况下,6 级流水 的速度是不采用流水技术的6 倍
- 实际上,流水段之间会加上锁存器,这个锁存器用于保存前面流水段的操作结果,同时为下一段提供操作数据和操作信号
- 指令1在第一个流水段的结果被存到锁存器之后,指令2也可以使用这个结果
(2) 运算流水线结构
流水线不仅仅用于指令,像运算也能使用流水线技术以提高速度
比如说浮点数运算,就很复杂
完成 浮点加减 运算 可分 对阶、尾数求和、规格化 三段
分段原则 每段 操作时间 尽量 一致
学习思想:事实上,其他的复杂的操作,都可以这样分段,做成流水段
- 分段的思想也是 时间 尽可能一致
- 如果不等,那么时钟周期就要按照最长的那一段来,这样会降低整个流水线的速度
8.4 中断系统
中断系统的应用非常多,第五章的输入输出,程序调试以及处理异常方面都可以使用中断
8.4.1. 概述
(1) 引起中断的各种因素
-
人为设置的中断
如 转管指令,就是人为设置指令中断
-
程序性事故
溢出、操作码不能识别、除法非法等
-
硬件故障
-
I/O 设备
-
外部事件
用 键盘中断 现行程序
每种中断原因都有一个中断源
(2) 中断系统需解决的问题
- 各中断源 如何 向 CPU 提出请求 ?
- 各中断源 同时 提出 请求 怎么办 ?
- CPU 什么 条件、什么 时间、以什么 方式 响应中断 ?
- 如何 保护现场 ?
- 如何 寻找入口地址 ?
- 如何 恢复现场,如何 返回 ?
- 处理中断的过程中又 出现新的中断 怎么办 ?
这几个问题无非就是软件和硬件处理,后面针对这些问题一个个解决,注意哪些用软件,哪些用硬件
8.4.2. 中断请求标记和中断判优逻辑
解决的问题就是:
- 各中断源 如何 向 CPU 提出请求 ?
- 各中断源 同时 提出 请求 怎么办 ?
(1) 中断请求标记
- 每一个中断源都有一个 INTR 中断请求标记触发器,用来标记中断源是否提出了中断请求,中断源通过这个请求标记提出请求
- 多个中断源的多个INTR,在逻辑上组成了中断请求标记寄存器(一位是一个触发器记录的)
这个寄存器的分部方式有两种
- INTR 物理上分散 在各个中断源的 接口电路中,在逻辑上构成了寄存器
- INTR 集中 在 CPU 的中断系统 内
(2) 中断判优逻辑
各中断源 同时 提出 请求 怎么办 ?该响应哪一个
通常情况下,根据中断源产生事件的严重程度对中断源进行分级,就是中断源的优先级
① 硬件实现(排队器)
现代计算机中,大多数的中断判优都是通过硬件实现的
有两种方法
-
中断请求标记 分散 在各个中断源的 接口电路中
比如说 第五章的链式排队器,每个中断源中都有一个非门和与非门,多个中断源的判优电路连接在一起
-
中断请求标记 集中 在 CPU 内
INTR1 、 INTR2 、 INTR3 、 INTR4 优先级 按 降序 排列
如果INTR1 有信号的话,那么输出的必定是1
对于INTR2,如果INTR1有信号的话,那么与非门的结果是1,非门的结果是0.导致最终的INTP2 = 0
由此可见,只有当前面的全部无效的情况下,该中断才能有效
排队器的输出中,只有一根线是1,其余都是0
② 软件实现(程序查询)
A、B、C 优先级按 降序 排列
8.4.3. 中断服务程序入口地址的寻找
如何 寻找入口地址 ?
(1) 硬件向量法
上述排队器会产生一个中断向量地址
如何根据中断向量地址得到 中断服务程序的入口地址呢?
有两种方法给出
-
在中断向量地址的存储单元之中,存放一条跳转指令,跳转指令包含中断服务程序的地址
也就是要执行这条跳转指令
-
在中断向量地址的存储单元之中,保存的就是中断服务程序的入口地址,将这个地址取回来送到PC中,PC自动从中断服务程序开始执行
对应表如下
中断向量地址 | 中断服务程序的入口地址 |
---|---|
12H | 200 |
13H | 300 |
14H | 400 |
特点:速度快,设计灵活性较低
(2) 软件查询法
用软件如何实现寻找中断服务程序的入口地址呢?
假设八个中断源 1,2,.... 8 按 降序 排列,通过执行中断识别程序进行查找
假设中断识别程序的入口地址是M,程序的指令和说明如下
SKP的含义是跳过下一条指令
SKP DZ 1 的意思是查询第一号中断源的完成触发器D
如果D = 1,说明中断源已经准备好了,跳转到1的中断服务程序
如果D = 0,跳过下一条程序,查询第二号中断源
8.4.4. 中断响应
CPU 什么 条件、什么 时间、以什么 方式 响应中断 ?
(1) 响应中断的条件
并不是中断源提出中断服务请求CPU就要立即响应
假如CPU只能支持单重中断
单重中断:CPU在相应某一个中断源的中断请求,并且开始执行中断服务程序的情况下,即使有新的中断请求,CPU也不能响应
为了表示CPU是否允许响应中断请求,CPU内部有一个EINT允许中断触发器
EINT = 1的时候,才会响应中断请求
(2) 响应中断的时间
不是任何时间(比如说指令的执行过程中)都可以响应的
指令执行周期结束时刻由CPU 发查询信号,就是指令执行阶段结束之后
这与之前学过的 指令的接受周期的分段一致
有些计算机某些指令比较复杂,执行时间可能比较长,为了能够及时处理异常事件,允许CPU在执行指令的过程中进行中断响应。通常情况下载指令执行结束之后
思考:为什么在指令执行结束之后响应中断?
指令执行周期结束时刻由CPU 发查询信号
查询信号会驱动中断请求触发器,将触发器的输出端置一,然后发送到排队电路
(3) 中断隐指令
如果需要响应某个中断请求,CPU如何响应中断请求?
-
响应中断,要去执行中断服务程序
-
为将来的中断返回做准备
- 保护程序断点
- 保护程序运行的软硬件状态
-
单重中断:执行中断服务程序时不允许再发生中断
多重中断:保护程序软硬件状态的过程中,不允许发生中断多重中断中,不允许优先级低的请求打断优先级高的请求,所以多重中断中EINT也是有用的?
不是,这里也是要判断优先级呀,有用的,在保护现场和断点的时候,需要关中断防止打断
中断响应的过程中,要解决下面的问题
中断隐指令完成下面的三个操作
事实上,中断周期就是干下面的三件事,这三件事还都是硬件完成的,至于中断服务程序,那里面又是新的指令了,就跳转到新的解释指令周期中了
① 保护程序断点
程序断点就是 中断服务程序结束之后,返回的源程序要执行指令的地址,就是一个地址
有两种办法保护断点
- 断点存于 特定地址( 比如0 号地址) 内,这个地址是内存的一块存储单元
- 断点 进栈,返回的时候出栈即可
② 形成服务程序入口地址
- 向量地址——>PC(硬件向量法),PC中保存了入口地址,或者跳转指令
- 中断识别程序 入口地址 M —> PC(软件查询法)
③ 硬件关中断
- 关中断是为了避免在单重中断的计算机中,在执行中断服务程序的过程中,有新的中断源发出中断请求,打断当前中断服务程序的执行
- 即使在多重中断中 也要在 保护程序断点和现场的时候关中断
关中断就是将EINT置为0
我们来看下面的示意图
-
EINT输出为1,传入到INT下面的与非门中
-
如果有中断请求,排队器的输出有且仅有一个1,使用一个或门,输出1就表示是有请求,也加入到与非门中
-
当EINT = 1 且 有请求的时候, INT = 1,表示有中断请求
并且INT的1送回到EINT,此时EINT置为0,表示不能接受中断
-
排队器的输出会送到向量地址形成部件 形成 中断服务程序的入口地址送到PC中
隐指令是指上面的三个步骤是由硬件自动执行的,并不是计算机指令集中的某个指令控制执行的
8.4.5. 保护现场和恢复现场
(1) 保护现场
保护现场分为两点
任务 | 完成 |
---|---|
断点 | 中断隐指令完成,上面说过 |
寄存器内容 | 中断服务程序完成 |
- 在执行中断服务程序的时候,也需要寄存器,但是返回源程序后,仍然需要原来寄存器保存的内容,因此要将寄存器的内容先存起来,中断服务程序结束之后再恢复
- 这个由中断服务程序完成
(2) 恢复现场
也是由中断服务程序完成,在结束的时候完成
下面是中断服务程序的流程
8.4.6. 多重中断
如果在执行中断服务程序的过程中,出现了更重要的,需要及时处理的新事件,怎么办呢?
(1) 概念
CPU在执行中断服务程序的过程中,有新的中断源提出请求并且新的中断请求的优先级大于当前请求,就要进行响应
程序断点 k+1 , l+1 , m+1
注意程序断点的概念
(2) 实现多重中断的条件
-
要允许CPU在执行某个中断服务程序时,响应新的中断请求
做法:提前 设置 开中断 指令
-
是不是任何一个新的中断请求,均能中断正在进行的中断服务?
答:优先级别高 的中断源 有权中断优先级别低 的中断源
下面以图示的方式来看多重中断
中间可以看到
- 由于D 的优先级较低,在执行C的时候不会执行D,C执行结束之后才执行D
- A的优先级较高,在执行D的时候跳到A执行,然后再返回D执行
- 所有中断服务程序结束之后,返回主程序
(3) (中断)屏蔽技术
第五章的时候,已经学过了中断屏蔽技术
使用屏蔽技术,通过设置中断屏蔽字,来改变优先级,从而提高系统设计和响应的灵活性
中断屏蔽字保存在中断屏蔽触发器中
① 中断屏蔽触发器的作用
屏蔽触发器就是让某个中断源无法向CPU提出请求,也不能参加中断请求的排队,就是在多重屏蔽的时候进行优先级判断的
在某个中断服务程序的时候,设置屏蔽字,这样只有优先级更高地能够发出请求执行中断服务程序
下面以图示的形式来看看中断屏蔽触发器如何影响中断请求的,我们以外部设备提出中断为例
- 如果INTR在外部设备处分布,而非集中式分布,使用这个方法
什么时候INTR的输出为1
-
D的输出为1,(D是完成触发器,外设准备完成之后,发出中断)
-
MASK为0,此时Q非的输出为1
两个输出经过与非门和非门,只有两个都为1,也就是D输出为1,MASK值为0的时候,INTR的D口输入才为1
-
此时如果CPU发来查询之后,INTR才为1
对于屏蔽触发器,只有当MASK = 0的时候,INTR才能被置1
下面来看看如何设置优先级
- 当排队器集中在CPU内部或者某个击中的部分,可以使用屏蔽触发器来排队,就是将排队器与中断屏蔽触发器结合使用
MASKi组成了中断屏蔽字
如果MASKi = 1,,表示对应的中断服务请求无法提出
总的来说,屏蔽触发器就是让某个中断源无法向CPU提出请求,也不能参加中断请求的排队
屏蔽字只控制某个中断源能否发出请求或者发出的请求能否进行排队,但是如果两个中断源的请求都参与到排队,说明这两个的优先级都大于当前的优先级,都可以插入到当前的中断服务程序
但是具体是哪个插入呢?这就是根据原始排队器对这两个排队了,这就是响应顺序,由排队器的硬件结构决定,无法更改
② 屏蔽字
16个中断源 1,2,3 , 16 按 降序 排列
屏蔽触发器构成了屏蔽字
- 每一个中断源对应一个屏蔽字,就是在这个屏蔽字下,这个中断源无法发出请求或者请求不能参与排队
假设优先级最高的1号中断源的中断服务程序正在执行,然后设置屏蔽字,这样1~16号中断源都无法参与排队
③ 屏蔽技术可改变处理优先等级
一定要高清楚响应优先级和排队优先级的区别
中断的优先级分为响应优先级和处理优先级
-
响应优先级
不能改变,这是由硬件决定的:
-
处理优先级:可改变,通过设置中断屏蔽字,让一些中断源的请求不能参与排队来设置优先级,也就更不会响应
理解:
屏蔽字只能控制某些中断源能否发出请求或者请求能否参与排队,这是处理优先级
而如果多个中断源的请求都参与了排队,说明其优先级都大于当前中断服务程序对应的优先级了,都可以打断当前程序
此时,这些中断源的优先级是根据原始排队器进行排队的,排队的优先级也就是响应优先级,其是由排队器的硬件结构决定的
- 响应优先级 A→B→C→D 降序排列
- 处理优先级 A→D→C→B 降序排列
- 主程序的中断屏蔽字是全0
原屏蔽字 | 新屏蔽字 |
---|---|
![]() |
![]() |
-
ABCD同时请求中断:这个时候还是主程序执行,屏蔽字为0000,此时使用原始的排队器得到A 的优先级最高
-
原屏蔽字中,A程序执行的时候,设置屏蔽字为1111,这样BCD都无法插入了
-
新屏蔽字中,A处理完之后,屏蔽字设置为0000,这样BCD都可以进行排队
原始排队器排得到B 的优先级最高B执行,然后设置屏蔽字为0100,这是优先级最低的,CD都可以发出请求
CD发出请求后,再由排队器进行排队,响应优先级为C优先,执行C,设置屏蔽字为0110,这个优先级允许D的请求排队
D的请求参与排队,只有一个参与排队,必定是D,然后自然而然地打断C
D执行结束之后,倒序往回走
注意第二个图的左边的那个梯形
④ 屏蔽技术的其他作用
可以 人为地屏蔽 某个中断源的请求
⑤ 新屏蔽字的设置位置
注意开关中断和屏蔽字设置恢复的位置
设置屏蔽字必须要开中断之前
开关中断的权利要大于设置屏蔽字的权利,利用这个理解
(4) 多重中断的断点保护
断点可以保存到两种地方
- 断点进栈
- 断点存入“0”地址,此处的0打引号,并不是真正的0地址,而是指定的一个地址
这两个都是由中断隐指令完成
在中断周期(也就是解释指令周期的最后一个阶段),要做以下工作
- 保存断点 0 → MAR(假设保存到到0地址,将0送到MAR)
- 命令存储器写
- PC → MDR;PC中保存着断点,将断点给MDR
- (MDR) → 存储存储器
在多重中断中,存在问题
- 三次中断,三个断点都存入 “ 0 ” 地址,后面的断点会覆盖到原来的断点
如何保证断点不丢失?
看以下的程序
程序断点存入 “ 0 ” 地址的断点保护
地址 | 内容 | 说明 |
---|---|---|
0 | XXXX | 存程序断点 |
5 | JMP SERVE | 5为向量地址,就是排队器排队结果之后指向了5,5跳转到中断服务程序,SERVE就是中断服务程序的首地址 |
SERVE | STA SAVE | STA就是STORE ACC,将ACC寄存器的值存到SAVE这个单元中 |
…… | 其他的如保护寄存器内容的指令 | |
LDA 0 | 将0地址,也就是程序断点存到了ACC寄存器中 | |
STA RETURN | 将ACC的值存到RETURN这个存储单元中,一位无法直接将内存的东西转移到另一个内存单元中,得借助寄存器 | |
在这个时候,设置屏蔽字 | ||
…… | 其他服务内容 | |
LDA SAVE | 将SAVE的内容,也就是原先的ACC的内容再恢复到ACC中 | |
JMP @RETURN | 间接寻址,RETURN中保存着断点,跳到RETURN中的地址处(不是跳到RETURN处) | |
SAVE | XXXX | 存放ACC的内容 |
RETURN | XXXX | 转存0地址的内容 |