9.1 中断和异常的来源

计算机组成

9 中断和异常

9.1 中断和异常的来源

Screen Shot 2018-09-30 at 9.29.33 am

大家好,我就是一个CPU。那我的任务呢就是进行运算,有人交给我了一个本,上面写了很多的算式,让我进行运算。那我就开始算了,上面写着3*4,我一算是12,填在后面的空格里;还有呢15+15,等于30,填在后面的空格里。接着运算下一条,1234567*7654321,这个一算,结果好长啊,后面这个空格只有这么大,填不下。这可怎么办呢?

Screen Shot 2018-09-30 at 9.29.42 am

早期的电子计算机功能非常明确,就是进行数学运算。但是如果运算出现了异常情况那应该怎么办呢?因为计算机当中都只能提供有限的单元来表示一个数,所以,有时候就会出现运算结果过大,无法全部保存的情况,这就叫做溢出。

Screen Shot 2018-09-30 at 9.29.52 am

如果从这个模型机上来看,溢出就会发生在ALU这个运算单元上。这个运算单元的源操作数要么来自于寄存器,要么来自于内存。我们假设都是32位的,对它们进行运算。比如说进行加法,那么运算的结果就有可能超过32位。假设在内存当中的某一条运算指令发生了溢出,那么CPU能怎么办呢?运算发生了溢出,CPU的硬件电路是很容易检测到的。但问题就在于检测到了溢出之后应该怎么办?如果完全用硬件电路来处理溢出,那样不够灵活。一旦CPU制造出来我们就没办法改变这个电路,从而没有办法修改处理溢出的方法。所以,最好还是用软件的方法来解决。

那么来看看早期的计算机是怎么来解决这个异常的情况。

Screen Shot 2018-09-30 at 9.30.00 am

这是UNIVAC,也就说ENIAC的主要设计者埃克特和莫克丽,在离开宾夕法尼亚大学独立创办公司之后设计的那台计算机。

这是第一个带有异常处理的计算机系统。如果它在进行运算时发生了异常情况,比如算术运算溢出,它就会转向地址0,执行两条修复指令。这个方法的思想是非常重要的,不然的话,一旦出现异常的情况,就只能停机,然后等人工来解决问题以后才能继续运行。而如果我们能在地址0这里存放几条指令,用于修复这个异常的情况,从而就有可能在修复完成之后继续执行刚才的运算。这样就可以避免停机。而且如果之后发现这样的修复方法不太合适,只需要通过修改存放在地址0的这个地方的指令就可以。用这样的方法来处理异常就非常的灵活和便利。而这种思想也一直延续到现在,现代计算机的CPU处理异常从根本上来说也是采用了这个方法。

Screen Shot 2018-09-30 at 9.30.09 am

那么结合我们现在讲的CPU的结构,来看看这个方法的简单原理。

在ALU进行运算完成之后,硬件电路就很容易检测出这次运算是否发生了溢出。所以,我们可以在ALU这里增加一根信号线,连到PC的更新部件(PC updata),那原先这个PC的更新部件会从几个来源对PC进行选择:

要么增加一个固定的值,比如说PC+4;

要么是根据转移目标地址产生一个新的PC;

那么现在增加一种新的情况,就是当运算溢出的信号有效时,这个部件(PC update)就固定产生0,送到PC寄存器。这样在下一个周期,PC寄存器就会从地址0取出指令进行执行。那么执行若干条指令之后,就可以修复这个异常带来的影响。或者至少标记出了这次运算是错误的,以免对后续造成影响。那如果再通过一些方式,可以记住刚才发生异常时的PC的值,就可以再通过PC update部件,将这个值装入PC寄存器当中去,从而从刚才发生异常的地方开始继续执行。

这就是一个简单的处理运算结果异常的方式。

Screen Shot 2018-09-30 at 9.30.18 am

不过后来的计算机就不仅仅是只进行数学运算,还要与外界进行很多的交互,我们现在的计算机当中有很多的输入输出的部件。当CPU在运行程序的时候,有可能我们就会在键盘上按一个键,或者网络上来了一个数据包,这些输入输出的操作都需要CPU中断现有程序的运行来进行处理,这样的需求其实在很早也就有了。

Screen Shot 2018-09-30 at 9.30.26 am

1954年的DYSEAC是第一个带有外部中断处理的系统。这台计算机也可以说是最早的移动计算设备,说到移动计算设备,你可能会想到笔记本电脑或者平板电脑。不过这台计算机的移动性和他们有点不太一样,它是要挂在卡车上移动的,不过它确实是在移动着进行计算。和UNEVAC处理异常的方式不太一样,它设置了两个程序计数器,然后根据外部输入输出设备的信号,可以在这两个程序计数器之间进行切换,这样它就可以交叉执行两段不同的程序,一段程序是运算的功能,而另一段程序是专门用于处理外部的中断。

Screen Shot 2018-09-30 at 9.30.35 am

那后来UNIVAC也增加了对外部中断的处理,用于对风洞数据的实时收集。

Screen Shot 2018-09-30 at 9.30.44 am

那么简而言之,刚才提到的场景都是CPU在运行的时候遇到的一些事件。这些事件有可能是现行程序本身出现的,也有可能是在CPU的外部,甚至是整个系统的外部出现的事件,这时就要求CPU强行中止现在正在运行的程序,并且从一个新的存储器区域启动相应的程序去处理这些事件。还有一点也很重要,就是在处理完这些事件之后,CPU需要恢复到原来的程序继续运行。这些事件就被称为中断或者异常。

那究竟中断和异常又有什么区别呢?

Screen Shot 2018-09-30 at 9.30.53 am

那其实在这件事情上也没有明确的定论。不同的体系结构,不同的书籍,不同的研究群体,对它们的定义都有区别。其命名方式大体上可以分为这么几类。

一种是把CPU内部运行程序产生的这些事件,称为内部中断;而把CPU外部那些输入输出设备产生的事件称为外部中断。而这些所有的事件又统称为中断。

第二种方式则是将CPU运行程序所引发的特殊的事件称为软件中断;而把外部的这些输入输出设备产生的事件称为硬件中断。这种方式就是把运行程序看做一种软件的行为;而把外设的工作则归为一种硬件的行为。

还有一种常见的方式就是将外部设备发生的这些事件,称为中断;而将CPU内部运行程序发生的这些事件称为异常。这也是一种常见的命名方式。

但是对这些事件的统称,也是有不同的表示方式。有一些把中断和异常统称为中断。也有些地方把中断和异常统称为异常。

这些不同的名词是从不同的角度来理解和表述这件事情,但它们所代表的内部事件和外部事件的具体行为都是一样的。在我们的课中将采用中断这种统称,而在具体划分上主要采用外部中断和内部中断的表述方式,但也会根据不同的场景有时也使用其他的表述方式。这请大家注意。

Screen Shot 2018-09-30 at 9.31.02 am

那好了,现在制造这本手册的人告诉我。如果你发现运算的结果在这空格里填不下的话,也不要着急,就翻到这个手册的最前面,这个手册最前面的第一行,就写了应该怎么处理这种情况,照着这个往下做就可以了。这样事情就很简单了,但是随着我这个运算任务越来越多,我可能会遇到新的问题。突然发现不是空格写不下了,而是这个字母我不认识,或者这个运算符我没见过。那应该怎么办呢?

posted @ 2018-10-03 21:37  houhaibushihai  阅读(453)  评论(0编辑  收藏  举报