第08章 中断及8259
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第8章中断技术
中断是微机原理中的一种非常重要的技术,是CPU和外部设备进行数据交换的一种很有效的方法。
在本章中将对中断技术做详尽的分析,在此基础上对中断控制器8259A做详细介绍。
8.1 中断的概述
1. 中断及其相关概念
所谓中断(Interrupt),是指计算机在运行过程中,当有某些紧急事件或外设请求发生时,迫使CPU暂时中断现行程序的运行而去处理紧急情况或外设请求,即去执行其对应的中断服务程序;等到事件处理完毕,又返回原程序的中断点处,继续执行被中断的程序。
这个过程和机制称为中断。
计算机正运行程序A,由于某一个事件发生,暂停A程序的运行,而执行紧急事件处理程序B,程序A被中断时的下一条指令地址称为断点或断点地址。
当计算机对紧急事件处理完后,要返回原程序A,实际上是从断点处继续执行原程序,这个过程称为中断返回。
中断事件的处理程序B,称为中断服务程序。
中断服务程序是程序员事先安排好的。
紧急事件或外设请求事件发生的时间是无法预知的,但事件的性质及处理方法则是已知的。
计算机正运行程序A,受到紧急事件的要求,中断了当前程序A;在中断时刻,程序A 运行的当前状态称为中断现场。
它应包括状态寄存器的状态,以及CPU内部寄存器的当前内容。
为了使中断返回后这些信息不会丢失,必须加以保护,这称为保护现场。
保护的方法有时是靠硬件自动完成的,有时则靠程序来实现。
2. 中断的用途
(1)CPU与I/O设备并行工作
在中断系统引入之前,计算机完全在程序的控制下完成I/O操作,I/O设备的整个工作过程都是在CPU的直接监督控制下完成。
如CPU从一个输入设备读取数据,要不断地询问设备的数据是否准备就绪,如果没有准备好,CPU则继续查询直到数据准备好后才将数据读入,接着又查询下一个数据的准备情况,一直到把要求的所有数据读完为止。
这个过程中CPU和输入设备是在串行工作,串行工作浪费了CPU大量的时间。
引入了中断系统后,当输入设备数据准备就绪,则向CPU发出中断请求信号,CPU就停止了当前程序,进入中断服务,将输入设备准备好的数据读入,并做处理,工作完成后又执行原程序。
一般这段中断服务程序是很短的,而输入设备数据的准备工作是较长的。
CPU 在中断服务后去执行原程序,输入设备同时继续准备下一个数据。
从宏观上看,CPU和输入
设备是在并行工作,并行工作提高了CPU的工作效率。
(2)实现实时处理
所谓实时处理,是指某个事件或现象出现后及时地进行处理。
例如计算机控制一个化工生产过程,当出现压力过大,温度过高,已经到了极限值时,这种状况必须送到计算机及时处理。
因为这种情况不是生产的正常过程,出现的时刻也是随机的,无法预测的。
因此可用中断方法,当有告警信号时启动一个中断过程,使计算机立即停止当前的程序而转去中断服务,迅速采取措施,保证生产的安全运行。
(3)多道程序或多重任务的运行
由于CPU的速度越来越快,而I/O设备的速度已远远低于CPU,于是可以在操作系统的控制下,使CPU同时运行多个程序或执行多重任务,这必须借助于中断。
在一个程序运行中,可以由I/O的中断系统切换到另一个程序去运行,也可以分配每个程序一个固定时间间隔,利用时钟定时中断进行多个程序的切换。
(4)故障处理
计算机在运行过程中,往往会出现事先预料不到的情况,或出现一些故障。
如电源突跃,存贮器出错或运算出错等等。
计算机可以利用中断系统自行处理,而不必停机或报告工作人员。
3.中断源、中断源的分类及中断优先权
引起中断的原因,或能发出中断申请的来源,称为中断源。
通常中断源有以下几种:
(1)一般的输入、输出设备。
如键盘、纸带读入机、行打印机等。
(2)数据通道中断源。
如磁盘、磁带等。
(3)实时时钟。
在控制中,常常遇到时间控制,如果应用CPU执行一段程序来实现延时,则CPU在这段时间内不能干其它的工作,降低了CPU的利用率;经常应用外部时钟电路,当需要定时时,CPU发出命令,令时钟电路(这样的电路的定时时间通常是可编程的——即可用程序来确定和改变的)开始工作,待规定的时间到了后,时钟电路发出中断申请,由CPU 加以处理。
(4)故障源。
例如电源掉电,就要求把正在执行的程序的状态——IP、各个寄存器的内容和标志位的状态保留下来,以便重新供电后能从断点处继续运行。
另外,目前绝大部分微型机,RAM是使用半导体存储器,故电源掉电后,必须接入备用的电池供电电路,以便保护存储器中的信息。
一般在直流电源上,并上大电容,使其因掉电或电压下降到一定值时就发出中断申请,由计算机的中断系统执行各项操作。
(5)为调试程序而设置的中断源
一个新的程序编制好以后,必须经过反复调试才能正确可靠地工作。
在程序调试时,为了检查中间结果,或为了寻找错误,往往在程序中设置了一些断点,或进行单步工作(一次只执行一条指令),这些就要由中断系统来实现。
中断源是多种多样的,就其性质讲,可分为内部中断和外部中断。
所谓外部中断,一般是指I/O设备或其它硬件电路所引起的中断。
它的特点是通过硬件
向CPU发出中断请求信号,经常称外部中断为硬件中断。
外部中断又分为非屏蔽中断(NMI)和可屏蔽中断(INTR)。
所谓内部中断,主要指CPU内部中断,是通过指令设置的中断。
所以内部中断也称为软件中断。
使用软件中断,其功能类似于子程序调用。
只是这些子程序大部分是系统提供的,所以这类子程序的调用相当于高级语言中的库函数的调用。
在中断系统里,将全部中断源按中断性质和处理的轻重缓急进行排队并给予优先权。
所谓优先权,是指有多个中断源同时申请中断时CPU对中断响应的优先次序。
在中断源数量较多时,为了便于及时处理,把所有的中断分成若干级(称为中断级),首先按中断级确定优先次序,然后在同一级中再确定各个中断源的优先权。
8.2 中断的一般过程
当有中断源向CPU发出中断请求,CPU接收到请求并在一定条件下,暂时停止执行原来的程序而转去中断处理,处理好中断服务后再返回继续执行原来程序,这就是一个中断过程。
中断的处理过程大体上可分为:中断请求、中断响应、中断服务和中断返回四部分。
一般中断请求和中断响应由硬件可以完成;中断服务则是由用户编写的。
所以,中断的处理过程是由软件与硬件的结合完成的。
(1)中断请求
中断请求信号是由中断源向CPU发出的。
中断源可以是外部事件,也可以是CPU的内部事件。
外部事件的中断请求是外部设备向CPU中断请求引脚发出的电平或边沿信号。
内部事件的中断请求可以是CPU执行一条中断指令使CPU进入中断处理过程,也可以是CPU执行程序的结果使CPU进入中断处理过程。
(2)中断响应
CPU在没有接到中断请求信号时,一直执行原来的程序。
由于外设的中断申请随机发生,有中断申请后CPU能否马上去为其服务呢?这就要看中断的类型。
若为非屏蔽中断申请,则CPU执行完正在执行的那一条指令后,做好保护工作即可去服务;若为可屏蔽中断申请,CPU 只有得到允许才能去响应。
这就是说CPU能否在接到中断申请后立即响应要视情况而定。
对可屏蔽的中断申请,CPU要响应,必须满足以下三个条件:
a)无总线请求;
b)CPU允许中断;
c)CPU执行完现行指令。
CPU响应中断要自动完成三项任务:
a)关闭中断;
b)CS,IP以及PSW的内容推入堆栈(保护断点);
c)取得中断服务程序入口地址,进入中断服务。
(3)中断服务
一旦CPU响应中断,就可转入中断服务程序中。
中断服务包括以下六个过程:
①保护现场
将CPU中一些寄存器的内容加以保护,保护哪些寄存器则由用户视情况而定。
由于中断服务程序中也要用到某些寄存器,若不保护这些寄存器在中断前的内容,中断服务程序会将其修改,这样,从中断服务程序返回主程序后,程序不能正确执行。
由用户保护寄存器的这段程序称保护现场,实质上是执行PUSH指令将需要保护的寄存器内容推入堆栈。
②开中断
CPU接收并响应一个中断后自动关闭中断,其目的是保证在响应时和保护现场时不允许其他的中断来打断它。
但在某些情况下,有比该中断更优先的情况要处理,此时,应停止对该中断的服务而转入优先级更高的中断处理,故需要再开中断,若没有更高级别的中断或不允许嵌套在此不必开中断。
③中断服务程序
中断服务程序的核心就是对某些中断情况的处理。
如:传送数据,处理掉电紧急保护,各种报警状态的控制处理等等。
④关中断
由于有②的开中断,因而在此处应对应一个关中断过程,以便下面恢复现场的工作顺利进行而不被中断。
⑤恢复现场
在返回主程序前要将用户保护的寄存器内容从堆栈中弹出,以便返回主程序后继续正确执行主程序。
恢复现场用POP指令。
要注意的是堆栈为先进后出数据结构,注意保护现场时寄存器的先后入栈次序要与出栈时次序相反。
⑥开中断返回
此处的开中断对应CPU响应中断后自动关闭中断,在返回主程序前,也就是中断服务程序的倒数第二条指令往往是开中断指令,最后一条是返回指令,执行返回指令,CPU自动从现行堆栈中恢复断点,以便继续执行主程序。
(4)中断返回
在中断服务程序最后安排一条中断返回指令,使断点送回程序计数器IP,继续执行被中断的程序。
8.3 8086中断系统
8.3.1 8086中断分类
8086/8088有一个强有力的中断系统,可以处理256种不同的中断,每个中断对应一个类型码,所以,256种中断对应的中断类型码为0~255。
从产生中断的方法来分,这256种中断可以分为两大类:一类叫外部中断;一类叫内部中断。
1. 外部中断
外部中断通常为外部设备需CPU处理相应外部事件而向CPU提出申请引发的中断。
外部中断是通过外部的硬件产生的,所以,也常常把外部硬件中断称为硬件中断。
硬件中断又可以分为两类:一类叫非屏蔽中断;另一类叫可屏蔽中断。
非屏蔽中断是通过CPU的NMI (Non-Maskable Interrupt)引腿进入的,它不受中断允许标志IF的屏蔽,并且在整个系统中
只能有一个非屏蔽中断。
可屏蔽中断是通过CPU的INTR(Interrupt)引腿进入的,并且只有当中断允许标志IF为1时,可屏蔽中断才能进入,如果中断允许标志IF为0,则可屏蔽中断受到禁止。
在一个系统中,通过中断控制器(如8259A)的配合工作,可屏蔽中断可以有几个、几十个。
(1)非屏蔽中断
从NMI引腿进入的中断为非屏蔽中断,它不受中断允许标志IF的影响。
当NMI引腿上出现中断请求时,不管CPU当前正在做什么事情,都会响应这个中断请求而进入对应的中断处理,可见NMI中断优先级非常高。
正因为如此,除了系统有十分紧急的情况以外,应该尽量避免引起这种中断。
在实际系统中,非屏蔽中断一般用来处理系统的重大故障,例如系统掉电处理常常通过非屏蔽中断处理程序来执行。
所谓掉电就是指电源电压持续下降。
例如,应为220V的外加交流电压在某个时候降为160V,并且还在继续下降,这就认为遇到了掉电事故。
此时电源系统就要通过CPU的NMI 引腿向CPU发非屏蔽中断请求。
CPU接收到这一请求后,不管当前在做什么,都会停下来,立即转到非屏蔽中断处理子程序。
非屏蔽中断处理子程序要在晶体振荡器停振之前将现场作出紧急处理。
一般采用以下措施之一:一是将当前现场保留到非易失性存储器中,以便电源恢复正常之后继续往下执行刚才被中断了的程序。
非易失性存储器即使在电源去除之后也能保留存入的数据;二是启动另外一套热备份的设备,以便马上利用另外一套系统来替换本系统执行控制、数据录入或运算功能。
三是启动一定的线路接通一个可充电的电源系统,以维持系统正常工作。
(2)可屏蔽中断
一般外部设备发出的中断都是从CPU的INTR端引入的可屏蔽中断。
当CPU接收到一个可屏蔽中断请求信号时,如果标志寄存器中的IF为1,那么,CPU会在执行完当前指令后响应这一中断请求。
至于IF的设置和清除,则可以通过指令或调试工具来实现。
已经提到过,可屏蔽中断的数目可以有许多个,因此要用中断优先级来进行管理。
当同时有几个可屏蔽中断请求到来时,CPU会首先响应和处理优先级别最高的一个中断;当CPU 正在处理某个中断时,如果外部又有优先级别比本中断更高的中断请求,那么,就可以实现中断的嵌套。
中断控制器就是具体执行优先级管理和排队的部件。
当8086/8088系统中使用中断控制器时,可以允许外部有多达几十个中断源。
2.内部中断
内部中断是由计算机内部执行指令产生的中断。
也称软件中断,内部中断是CPU根据软件中的某条指令或者软件对标志寄存器中某个标志的设置而产生的,所以内部中断可分为软中断指令引发的中断与CPU在特定条件下自身引发的中断。
软中断指令指INT n类指令。
CPU的特定条件是指CPU执行某条指令的结果或程序对标志寄存器某个标志位的设置。
从软件中断的产生过程来说,完全和硬件电路无关。
内部中断主要有除数为0中断、溢出中断、断点中断、单步中断和软中断(INT n中断)5种类型。
图8.1表示了8086系统中关于中断来源的分类。
类型0,1,3,4的中断称为内部中断,每个保留中断的处理过程都实现8086系统某一个特定的功能。
(1) 除数为0的中断
类型为0的中断称为除数为0的中断。
每当运算过程中遇到除数为0的情况,或者对有符号数进行除法运算所得商超出规定范围的情况(双字除以字的商范围为-32768~+32767,字除以字节,商的范围为-128~+127),则CPU 会自动产生类型为0的中断,转入相应的中断处理程序。
类型为0的中断既不是外部硬件产生的,也不是用软件指令产生的,而是CPU 自身产生的,因此0号中断没有对应的中断指令。
也就是说,指令系统中没有INT 0这条指令。
(2) 单步中断
类型为1的中断是单步中断。
CPU 进入单步中断的依据是标志寄存器中的单步标志TF 为1。
也就是说,和类型为0的中断类似,单步中断也不是由外部硬件或者程序中的中断指令产生的,而是由CPU 对标志位TF 的测试而产生的。
当然,对TF 标志的设置是通过指令实现的,不过这是通过传输指令完成的,并不是中断指令完成的。
单步中断的含义是每执行一条指令,就进入一次单步中断处理程序,此处理程序用来显示出一系列寄存器的值,并且告示一些附带的信息。
因此,单步中断一般用在调试程序中逐条执行用户程序。
调试程序为了用单步方式运行用户程序,在程序员设置单步调试命令之后,有一个专门的程序段会修改标志位TF ,并且用一个计数单元记录需要执行的单步中断的次数。
这里要强调的一点是,TF 的值是由调试程序修改的,而不是由被调试的程序修改的。
CPU 测试到标志寄存器中的TF 为l 时,就进入单步中断。
此时,按照一般的软件中断过程,CPU 把标志寄存器的值推入堆栈,清除当前标志寄存器中的TF 和IF ,再把断点地址推入堆栈,然后进入单步中断处理程序。
进入单步中断处理程序后,由于此时标志寄存器中的TF 为0,所以,CPU 不会以单步方式执行单步中断处理程序,而是以连续方式执行单步中断处理程序。
具体地说,就是显示一系列寄存器的值,必要时还指出一些重要信息,最后执行中断返回指令。
中断返回指令在执行时,从堆栈中弹出断点地址和标志寄存器的值,然后返回调试程序,并且使单步计数单
可 屏 蔽 中 断
请
求 图8.1 8086的中断分类
元的值减1。
由于从堆栈中弹出了标志寄存器的值,于是TF又变为1,所以在执行下条指令后,又进入单步中断处理程序。
然后又显示一系列寄存器的值,同时使单步计数单元的值减1……如此下去,会见到每执行一条指令,便显示一系列内部寄存器的内容,直到单步计数单元的值减为0时,调试程序又用传输指令将标志寄存器中的TF改为0,从而结束单步中断的状态。
单步中断为调试程序提供了逐条运行用户程序的手段,于是,可以在执行每条指令以后,检查这条指令进行了什么操作,是否得到了预期的结果。
这种调试手段对于检查用户程序中一些隐藏的错误往往很有用。
如果遇到程序中有带重复前缀的串操作指令,则在单步操作状态下,将在每次重复之后,产生一个单步中断,而不是在整个串操作指令结束后进入单步中断。
(3)断点中断
类型为3的中断称为断点中断。
断点中断也是8086提供给用户的一个调试手段,一般用在调试程序中。
一个比较长的用户程序往往要完成多个功能,而在编制好程序以后,一般总有这样或那样的一些错误,即使是有经验的程序员也难免,为此要对程序进行调试。
调试时,常用的手段就是设置断点和单步运行。
怎样从一个较长的程序中分离出一个较短的存在问题的程序段呢?
这就是断点中断要解决的问题。
当调试一个用户程序时,程序员一般把编写的程序分为几个程序段,每个程序段都应该达到一个预期的功能。
例如说,程序从100H开始,到200H 处应该完成一个浮点加法运算。
那么在调试时,程序员可以在程序所要求的单元中设置好几个初值,然后让程序运行到200H处停下来,看看运算结果是否正确。
为了做到这一点,就必须在200H处设置一个断点。
设置断点的过程,实际上就是在用户程序的指定点用断点中断指令INT 3来代替用户程序的原有指令,同时把用户程序的原有指令妥善保存起来,这样,当此后运行到断点位置时,便会执行指令INT 3。
INT 3指令在执行时,将使CPU进入类型为3的中断处理程序。
和其他软件中断进入过程一样,此时CPU要保存标志寄存器的值,清除当前标志寄存器中的TF和IF,然后保存断点地址,从而进入中断处理程序。
断点中断处理程序实际上是调试程序的一部分,它的主要功能就是显示一系列寄存器的值,并给出一些重要信息。
程序员由此可以判断在断点以前的用户程序运行是否正常。
此外,断点中断处理程序还负责恢复进入中断以前在用户程序中被INT 3所替换掉的那条指令;在中断返回之前,还必须修改堆栈中的断点地址,以便能正确返回到曾经被替换掉的那条指令所在的单元。
如果不修改断点地址,返回时指令指针将指向被替换掉的指令的下一个单元,也就是说,将少执行一条指令,甚至可能把多字节指令的下一个字节作为另一条指令的首字节,从而造成混乱。
断点中断处理程序在执行以后,CS和IP指向用户程序的下一条指令,CPU则处于调试程序状态。
此时,可以在用户程序中设置下一个断点,继续程序的调试工作。
8086系统也允许一次设置多个断点,这样,在调试用户程序过程中,会自动在第一个断点处、第二个断点处……停下,以便程序员检查运行结果。
如果用户程序中有转移指令或者调用指令时,会使程序并不是按顺序执行,这种情况下,有时设置断点这个动作本身就可能使用户程序产生错误的结果。
INT 3是一条与众不同的中断指令。
其他INT n形式的中断指令都是2字节的,但INT 3是1字节的,其原因就是为了在任何情况下都避免设置断点本身所造成的用户程序的错误。
(4)溢出中断
类型为4的中断称为溢出中断。
8086系统中,对于无符号数和有符号数的乘法指令和除法指令是各不相同的,但是对这两类数据的加法指令以及减法指令是相同的。
在某些情况下,无符号数的加、减运算和有符号数的加、减运算都可能造成溢出。
所谓溢出,就是超出了数据的规定范围。
对于无符号数来说,产生溢出并不是什么错误,这种情况下的溢出实际上是低位字节或者字往高位产生了进位或借位。
但对于有符号数来说,产生溢出就意味着出现了错误,所以应该避免,或者是一旦产生,便能立即发现。
在讲算术运算指令时进行过分析,即如果运算过程使CF为1,则表示无符号数运算产生溢出,这是允许的;如果运算过程使OF为1,则表示有符号数运算产生溢出,这就表示有了错误。
从另一方面说,如果是对无符号数进行处理,这时也可能会使OF为l,但不是什么错误。
如果这是对有符号数进行处理,那就意味着出错了,如不能及时处理,再往下运行程序,结果就没有意义。
对CPU来说,它并不能知道当前处理的数据是无符号数还是有符号数,只有程序员才明确这一点。
为此,8086指令系统提供了一条溢出中断指令INTO,它专门用来判断有符号数加、减运算是否溢出。
INTO指令总是跟在有符号数的加法运算或减法运算过程后面。
当运算指令使OF为1时,执行INTO指令就会进入类型为4的溢出中断,此时中断处理程序给出出错标志。
如果运算指令并没有使OF为1,那么,接着执行INTO指令时,也会进入中断处理程序,但此时中断处理程序仅仅是对标志进行测试,然后很快返回主程序。
由此可见,在对有符号数执行加法或减法之后,执行INTO指令可以对溢出情况进行测试,一旦有了溢出,便能及时告警。
INTO指令也是一条1字节指令。
8.3.2 中断向量及中断向量表
所谓中断向量,实际上就是中断处理子程序的入口地址,每个中断类型对应一个中断向量。
8086的中断系统是以位于内存0段的0~3FFH区域的中断向量表为基础的,中断向量表中最多可以容纳256个中断向量。
中断向量并不是任意存放的。
一个中断向量占4个存储单元,其中,前2个单元存放中断处理子程序入口地址的偏移量(IP),低位在前,高位在后,后2个单元存放中断处理子程序入口地址的段地址(CS),同样也是低位在前、高位在后。
按照中断类型的序号,对应的中断向量在内存的0段0单元开始有规则地进行排列。
例如,类型号为20H的中断所对应的中断向量存放在0000:0080H开始的4个单元中,如果0080H、0081H、0082H、0083H这4个单元中的值分别为10H、20H、30H、40H,那么,在这个系统中,20H号中断所对应的中断向量为4030:2010。