1、第第8章章 输入输出方法输入输出方法 8.1 输入输出的基本概念输入输出的基本概念 8.2 无条件方式输入输出无条件方式输入输出 8.3 查询方式输入输出查询方式输入输出 8.4 中断方式输入输出中断方式输入输出 本章要点本章要点 习题八习题八 返回章目录 8.1 输入输出的基本概念输入输出的基本概念 从第从第2章的图章的图2.1可以看到,计算机的硬件系统由可以看到,计算机的硬件系统由CPU、内、内存、外设三大部分构成,它们相互之间通过一组信息传递的公存、外设三大部分构成,它们相互之间通过一组信息传递的公共通道共通道总线联系在一起的。总线联系在一起的。CPU和内存构成了计算机的主和内存构成了计
2、算机的主机部分,是计算机中的高速设备。而大多数外部设备都是慢速机部分,是计算机中的高速设备。而大多数外部设备都是慢速设备,用来把从主机以外采集到的数据送入主机内部,或者把设备,用来把从主机以外采集到的数据送入主机内部,或者把主机内的数据传递到外部,外设中的外部存储器还可以存储大主机内的数据传递到外部,外设中的外部存储器还可以存储大量的数据。那么,量的数据。那么,CPU作为计算机的核心,它又是如何控制作为计算机的核心,它又是如何控制外设的呢?外设的呢? 8.1.1 外设接口外设接口 外部设备的种类繁多,功能各不相同,控制的方法也各式各样。很多外设由于速度与信号的关系,无法直接连接在总线上与主机进
3、行数据交换,需要在系统总线与外设之间设置一个“适配器”,又称为“接口”,用于把CPU来的控制命令转换成外设的控制信号,把外设的工作情况转换成CPU可以读取并处理的状态信号。 接口部件担负着总线信号与外设信号的转接工作。它一头与外设相连,能够从外设接收数据或向外设发出信号,另一头连接在系统总线上,能够直接接收来自总线的数据和控制信号,或者在适当的时候往总线发送数据。 CPU能够与内存进行数据交换,也可以与外设接口进行数据传递,两者工作的方式是非常相似的。从第2章的描述中我们已经知道,CPU如果要从内存读或向内存写一个数据,总是先在地址总线上发出地址信号,以选定操作对象,然后在控制总线上发出控制信
4、号,通知操作对象完成什么样的操作,数据总线则提供被交换的数据进行传递的通道。CPU总是通过总线,以发送地址信号的方式选择操作对象,对内存对外设接口都是如此。所以,计算机系统中对内存进行了编号,就是内存的物理地址,对外设接口也进行了编号,这个号码称作“外设端口号”。每一个端口号对应外设接口中的一个存放字节型数据的元件,称为一个“外设端口”。一个外设接口中往往需要多个外设端口,占据多个外设端口号。CPU控制外设就是通过从这些外设端口中读取数据以及向它们发送数据实现的。 在计算机内外数据交换过程中,外设总是处于从属状态,它受来自总线信号的控制,按控制命令的要求完成相应的操作,并且可以从主机接收或向主
5、机提供数据。所以大多数外设接口从功能上可以分为控制部件、状态部件和数据部件三大组成部分。控制部件又称为命令部件,专用于接收来自主机的操作命令,并转换成对外设的控制信号;状态部件负责向主机转达外设的当前工作情况;数据部件是内外数据交换的缓冲器,临时存放需要传递的数据。 通常,三大部件中的每个部件至少占据1个外设端口地址,每个端口都以字节为基本构成单位,因而1个外设接口一般最少占用3个端口地址。但是,有些外设能够接受的控制命令很少,只需要1字节中的1位或2位就够了,这时可以用1个控制端口的8个位分别控制不同的外设,把不同外设的接口集中在一起,共同占据一个外设端口号。另一方面,接口中的命令部件只用于
6、接收控制命令,CPU对命令部件只写不读。状态部件刚好相反,只用于向CPU提供状态信息,CPU对它只读不写。因而有些接口把命令部件与状态部件设计为共同占用1个外设端口号,由总线上的“读”或“写”信号区分究竟哪个部件是当前的数据传递对象。 8.1.2 8088的独立编址方式的独立编址方式 无论是内存还是外设端口,都是以字节为基本的数据单位。当总线上出现有效的地址信号时,每个字节型内存储器或外设端口都能够根据地址信号,判断自己是否被选中为数据传递的对象(完成这种判断的是地址译码器),没有被选中的自动不参与本次总线上的数据传递。从这个角度说,只要为内存和外设端口分别安排不同的地址,就可以从地址信号本身
7、区分数据传递的对象是内存还是外设端口,从而把各个内存字节与外设端口编排一套地址号码,这种编排地址的方式称为“统一编址”或“混合编址”。 8088采用的是另一种编址方式。由于8088CPU在数据交换时除了能够发出地址信号外,还有一根特别的信号线(IO/M)可以发出两种不同的信号。当这根信号线上发出高电位信号时,表示当前总线上是外设操作;反之,这根信号线上是低电位时,表示当前总线上是内存操作。设计计算机系统时就可以利用这根信号线上的信号,区分操作对象是内存还是外设。这时,各个内存字节与外设端口可以分开编排两套号码,分别称为内存地址与外设地址。当CPU需要读写数据时,同时发出地址信号和 IO/M信号
8、,这些信号一起送到地址译码器,地址信号选择了具体的地址号码,而 IO/M信号则选择内存还是外设。这种把内存和外设端口分开各自编址的方式称为“独立编址”。 8.1.3 控制外设的指令控制外设的指令 由于8088采取了独立编址方式,就需要有特殊的指令控制对外设端口的操作。8088系统设计有两条专用指令:IN和OUT。 【指令格式】IN d1, d2 【功能】从d2指明的外设端口中读取1字节或2字节数据,送到操作数d1指出的地方。 【说明】 (1)8088系统限制d1只能是AL或AX。当外设端口号不超过255时,d2操作数可直接写端口号码, 是外设的直接寻址方式;端口号超过255时,必须先把端口号放
9、在DX中,以DX作为d2操作数,这是外设的间接寻址方式。 (2)当d1是AL时,该指令从指定的端口中读1字节数据;当d1是AX时,CPU将从d2对应的端口读1字节数据到AL,从下一个端口号读1字节数据到AH,即总共读取16位数据送到AX 中。 【指令格式】OUT d1, d2 【功能】把操作数d2指明的1字节或2字节数据送到d1对应的外设端口中。 【说明】 (1)d2只能是AL或AX。当外设端口号不超过255时,d1操作数可直接写端口号码;端口号超过255时,必须先把端口号放在DX中,以DX作为d1操作数。 (2)当d2是AL时,该指令把AL中的8位数据送往d1指定的外设端口;当d2是AX时,
10、该指令把AL中的8位数据送到d1对应的端口,把AH中的8位数据送往下一端口,即把16位数据送到d1对应的端口及下一端口中。 IN和OUT指令专门用于外设操作,必须与内存操作严格区分开。下面的例8.1用来说明IN、OUT指令与内存操作的MOV指令之间的差别,并请读者体会在数据传递期间IO/M信号的作用。 【例8.1】说明下面各指令或程序段的功能。(1)MOV DX,61H IN AL,DX(2)MOV BX,61H MOV AL,BX(3)OUT 21H,AL(4)MOV SI,21H MOV SI,AL 【解】 (1)先把立即数61H放到DX中,然后以DX中的61H作为外设端口号,从相应的外设
11、端口读取1字节数据送到AL中。 (2)先把立即数61H放到BX中,然后以BX中的61H作为偏移地址,以缺省段寄存器DS 中的值为段地址,从相应的内存中取出1字节数据送到AL中。 (3)把AL中的1字节数据送往21H号外设端口。 (4)先把立即数21H放到SI中,然后以SI中的21H作为偏移地址,以缺省段寄存器DS 中的值为段地址,把AL中的1字节数据送到相应的内存中。 8.1.4 输入输出方式输入输出方式 外部设备是多种多样的,不同的设备需要不同的控制方法。CPU与外设之间进行数据传递时需要考虑外设的性能。对于多数慢速外设而言,如果CPU传送来的数据速度太快,外设来不及处理,就可能造成数据丢失
12、;如果外设还没有准备好数据,CPU就已经发出了读操作命令,将读不到正确的数据。因此,计算机系统进行内外数据交换时,必须根据外设的特点采用适当的形式。总的来说,主机与外设之间数据交换的方法有4种:无条件方式、查询方式、中断方式、DMA方式。 1无条件方式无条件方式 又称为直接方式,是指CPU可在任何时刻直接以外设操作指令与外部设备进行数据传递。显然,这种方式对外设有很高的要求,它必须能像内存一样时刻准备着与 CPU进行数据传递,并且能够跟上CPU的速度,保证传送的信息的正确性。 2查询方式查询方式 使用查询方式工作的外设必须至少有两个部件,其中之一是状态部件。CPU每一次与外设进行数据交换之前,
13、先从状态部件读取信息,判断外设是否处于“就绪”(Ready)状态。如果来自外设的状态信息反映出外设“没有准备好”或正“忙”(Busy),说明还不能进行数据传递;反之,当CPU检测到外设已准备好(Ready)后,可以与外设进行一次数据交换。 3中断方式中断方式 这是指每当外设准备好、能够进行数据传递时,就向CPU发出一个特殊的请求信号,称为中断请求信号。CPU收到中断请求后,暂停当前的工作,转而执行一段预先设计好的中断服务程序,完成对外设的数据交换。执行完中断服务程序后,CPU仍回到被暂停的程序继续执行。 4直接存储器存取直接存储器存取DMA(Direct Memory Access)方)方式式
14、 这是一种不通过CPU,在内存与外设之间直接进行高速数据交换的方法。通常,系统总线是在CPU的控制之下,CPU总是作为数据传递的一方,内存与外设其中之一作为另一方。当大量的数据需要传递时,在主机内部,数据不 可能完全放在CPU中,只能放在内存中。在CPU控制下进行大量数据的传递,就必须把内存中的数据读到CPU中,然后再写往外设,或者反方向,先把数据从外设读入CPU再写往内存。可见,数据必须以CPU作为过渡,才能到达它的目的地。DMA方式正是避免了这种过渡,让数据不经过CPU,直接从内存送到外设,或者反之。 进行DMA方式的数据传递必须有一个前提条件,就是CPU能够让出总线的控制权,交由DMA方
15、式数据传递的专用控制器控制,当数据传递结束后,CPU再收回总线控制权。8088CPU支持这样的总线操作方式,因而8088系统可以进行DMA方式的数据传递。 DMA控制器专门用于控制内存与外设之间的直接数据传递,但是它没有数据处理能力。在一些计算机系统中还设计有带有处理能力的专用数据传送芯片,其工作方式与 DMA方式很相似,也需要CPU在适当的时候让出总线供其使用,这种数据传递方式称为“专用处理机方式”。 8088微型计算机不使用处理机方式进行数据传递,DMA方式需要涉及计算机硬件的内容过多,所以本书都不做详细介绍。 系统总线 端口 61H: P7 P6 P5P4P3P2 P1 P01.193M
16、Hz 定时器 AB 与门 放大电路 扬声器 图8.1 扬声器与系统总线的连接8.2 无条件方式输入输出无条件方式输入输出 计算机系统中的扬声器是一种简单的输出设备,可以随时从CPU接收控制命令。图8.1是扬声器的连接原理图。 扬声器发声的基本原理是振动。扬声器口上的一层薄膜在电信号控制下往复振动产生声音,每秒钟振动的次数就是所发出的声音的频率,振动的幅度决定声音的强度。由于控制扬声器的信号是二进制的开关信号,不能对流过扬声器的电流的大小进行控制,因而不能控制扬声器薄膜的振幅,所以小扬声器只能发出固定强度的声音。但开关信号变化的频率是可控的,CPU正是通过控制开关信号的频率,让扬声器发出不同频率
17、的声音。 由图8.1可以看到,控制扬声器的信号有两个来源,它们通过与门之后送往放大电路并控制扬声器发声。系统中的61H号端口是一个可读写的外设端口,能够存放一字节数据,其中的最低两位就用来控制送往小扬声器的两个信号源。最低位P0为0可以保证送往与门A输入端的信号为高电位,这时只需要交替变化次低位P1的值,控制与门的另一个输入端B端的信号即可。除此之外,还要控制P1 变化的频率,比如要让扬声器发出500Hz的声音,就是要使P1位上的信号每秒钟变化500次,即每0.002秒是一个变化周期,因而要让P1位维持高电位(即置P1位为1)0.001秒,然后变成低电位,再维持0.001秒,如此交替变化。而发
18、声时间则通过控制P1位交替变化的次数来掌握,比如让扬声器在1秒钟内保持发出500Hz的声音,就要让P1位交替变化500次。 控制时间并不是件容易的事。如果要准确控制时间,可以参照微机原理中有关定时器的内容,采用后面说明的中断方式。在此只是为了说明直接数据传送的原理,故简化时间控制的方法,采用循环延迟的方式实现。需要说明的是,例8.2的程序虽然可以在各种档次的PC机上运行,但发出的声音频率有可能不一样。这是因为不同档次的机器执行循环延迟所花费的时间不同,而程序本身就是利用这个延迟来控制音频的。 【例8.2】利用无条件数据传送方式,让计算机的扬声器在1秒钟内保持发出500 Hz 的声音。 【解】完
19、整的程序如下: delnum = 14000 sta SEGMENT STACK DW 1024 DUP(0) sta ENDS code SEGMENT ASSUME CS:code,SS:sta delay PROC NEAR ;时间延迟子程序,以CX中的值作为 PUSH AX ;循环次数,做若干次的乘法产生时 PUSH DX ;间延迟的效果 del: IMUL AX ;用乘法指令延迟,执行时间较长 LOOP del POP DX POP AX RET delay ENDP main: MOV CX,500 sou: PUSH CX IN AL,61H ;读出原61H端口的数据 AND A
20、L,11111100B ;清最低两位 OUT 61H,AL ;送低电位到P1 MOV CX,delnum ;取控制延迟时间的循环次数值 CALL delay IN AL,61H OR AL,00000010B ;置P1位为1 OUT 61H,AL MOV CX,delnum CALL delay POP CX LOOP sou MOV AX,4C00H INT 21H code ENDS END main 从这个例子可以看出,对扬声器的控制是不需要任何条件的,程序中在向61H号端口送数据时根本不考虑扬声器是否准备好、是否可接收数据等问题。由端口61H到放大电路构成了扬声器的接口电路,该接口以系
21、统总线上送来的信号驱动薄膜的振动,按无条件方式进行数据传送。 8.3 查询方式输入输出查询方式输入输出 大多数外设不可能像扬声器那样工作,这些外设处理数据的速度和提供数据的速度往往比主机内部速度慢得多,因而CPU与这类设备进行数据传递前必须先判断它们是否“就绪”。CPU以查询方式从外设读取一批数据,以及向外设送出一批数据的流程如图8.2所示。Y读状态端口 Ready ? 处理完? NYN向数据端口写一个数据或向命令端口发一个操作命令 (b)查询方式输出操作流程(a)查询方式输入操作流程 读状态端口 Ready ? 从数据端口读一个数据处理完? NYNY 打印机是一种可以按查询方式工作的输出外设
22、,它与主机连接的接口部件是打印机适配器,也就是平常所说的“标准并行接口”或“并口”。打印机接口中的三大部件齐备,它们各自占据一个外设端口号码,分别是: 数据部件 378H; 状态部件 379H; 控制部件 37AH。 状态端口各位的含义如下: BusyACKPESELECTERROR D7 D6 D5 D4 D3 D2 D1 D0 (1)D7位:是打印机的“忙”信号。这一位为0表示打印机当前正处于“忙”状态,为1表示打印机不忙。 (2)D6位:是打印机送回的认可信号。当打印机从接口中正确接收1字节数据后,就送回一个低电位的认可信号,这个信号只维持很短的时间,然后又恢复高电位。 (3)D5位:缺
23、纸信号。这一位为1表示打印机无纸,因而无法打印,为0时表示正常工作。 (4)D4位:联机信号。这一位为1表示正处于联机工作状态,为0表示没有联机,这时不能工作。 (5)D3位:出错信号。为0表示打印机内部出现错误,不能工作,为1则正常。控制端口各位的含义如下: INTSELECTINITAuto FeedSTB D7 D6D5D4 D3 D2 D1 D0 (1)D4位:允许中断信号。将该位置1,允许打印机以中断方式工作,为0则不允许。 (2)D3位:联机命令。置1将设置打印机的联机工作方式,控制打印机时总是把这一位置1,否则打印机不能正常工作。打印机正常打印时这一位需要保持1。 (3)D2位:
24、初始化信号。正常工作时总是把这一位置1,需要把打印机重新初始化时,则在这一位先清0再置1,并且要维持清0的时间0.05秒以上。初始化又称作打印机复位,复位时可观察到的现象是打印头回到最左边。 (4)D1位:自动走纸。置1要求打印机在打印完一行后(回车时)自动走纸,清0时则需要向打印机输出换行符(0AH)控制走纸。这一位通常被置为0。 (5)D0位:选通信号。CPU通过在这一位上先置1再清0,通知打印机从数据部件中取走一字节数据并打印。 把图8.2中查询输出的流程稍做修改,可以作为控制打印机以查询方式工作的程序流程,如图8.3所示。 计数器清0 读状态端口 Ready ?送数据到数据端口送先高后
25、低的STB信号 打印完?计数器加1,取下一数据NYYN 结束图8.3 查询方式控制打印机 【例8.3】控制打印机以查询方式工作,打印26个英文字母,共打印30行。 【解】 sta SEGMENT STACK DB 1024 DUP(0) sta ENDS data SEGMENT print DB abcdefghijklmnopqrstuvwxyz,0DH,0AH data ENDS code SEGMENT ASSUME CS:code,SS:sta,DS:data init PROC NEAR ;打印机初始化程序 MOV DX,37AH MOV AL,08H OUT DX,AL MOV
26、CX,1000 init1: LOOP init1 ;延迟,维持初始化信号一段时间 MOV AL,0CH OUT DX,AL ;结束初始化,保持联机 RET init ENDP start: MOV AX,data MOV DS,AX MOV CX,30 ;30行 again: LEA BX,print ;待打印字符串首地址存放于BX中 next: MOV DX,379H wait: IN AL,DX TEST AL,80H JZ wait ;打印机忙,转去再读状态端口 DEC DX ;数据端口号 MOV AL,BX OUT DX,AL ;送数据到数据端口暂存 MOV DX,37AH MOV
27、AL,0DH OUT DX,AL ;置STB信号为1 DEC AL OUT DX,AL ;置STB信号为0 CMP BYTE PTR BX,0AH JZ newline INC BX JMP nextnewline: LOOP again MOV AX,4C00H INT 21Hcode ENDS END start8.4 中断方式输入输出中断方式输入输出 把例8.3的程序拿到计算机上去执行,可以发现从键盘上发出程序执行命令后,光标会停在命令的下一行闪烁,并且打印机开始工作,直到打印机打印完所有内容后才会出现系统提示符。也就是说,在打印期间,系统是不能做其它事情的。 分析一下例8.3的程序可以
28、发现,它是让高速的CPU去适应低速的打印机,让CPU反复不停地查问打印机的状态,直到打印机准备好。由于两者的速度差很大,很可能会出现CPU查问成千上万次以后才能等到打印机准备好的信号,送出1个字节的数据。显然,这种数据传递方式的效率是极低的。 设想让CPU把反复查问的时间利用起来去做别的事情,而让打印机在准备好接收一个数据时就向CPU发出一个信号。当CPU接到这个信号时,暂时停止正在执行的工作,以很短的时间为打印机送出下一个数据,然后恢复原工作。这样,尽管打印的速度并没有提高,但把高性能的CPU解放出来,可以做其它的事情,从而提高了整个系统的工作效率。中断式数据传递正是基于这种思想。 8.4.
29、1 中断的基本概念中断的基本概念 1中断中断 CPU暂停正在执行的程序,转去完成另一件工作,完成后再回到原来的程序继续执行的现象称为中断。 2中断源中断源 能够导致CPU中断的事件称为中断源。如果引发中断的事件来自CPU的内部,这样的中断源称为内中断源,比如CPU执行了一个会产生溢出的除法操作,就会产生一个内部中断。如果是由CPU外部的信号引发中断,这种中断源称为外中断源,打印机申请中断就是一种外中断源。 3中断源分类中断源分类 按照引发中断的中断源的位置不同,8088系统把中断源分为内中断源和外中断源两大类。来自CPU内部的中断请求是内中断源,8088系统的内中断源有除法溢出、执行中断指令和
30、单步中断(CPU每执行一条指令都产生一次的中断请求,主要用于程序的调试)。外中断源是来自CPU芯片外的中断请求信号,8088芯片有两个引脚可以接收外中断请求信号,分别是NMI和INTR,并且8088对这两个引脚上的中断请求信号的处理方式不太一样。根据中断信号来自哪一个引脚,外中断源又再分为两类:把中断请求信号通过NMI引脚送往CPU的中断源称为不可屏蔽外中断源,INTR上的则称为可屏蔽外中断源。 也可以按产生中断请求的方式不同,把中断源分为软件中断源和硬件中断源,由它们导致的中断又分别称为软中断和硬中断。除法溢出中断、单步中断是内中断源中的硬中断源,外中断源都是硬中断源。软中断则是由指令系统中
31、的中断指令导致的中断。 4中断号中断号 在计算机系统中,各种中断源都被统一地编排了一个互不相同的号码,用以唯一地标识一个中断源,这个号码称为中断号。在8088系统中,中断号的有效范围是0到255。常用的中断号与中断源的对应关系见表8.1。 5中断源识别中断源识别 由于中断源有不同的类型,向CPU申请中断的方式也各不相同。当CPU知道有中断请求后,还必须判断出究竟是几号中断请求。CPU确定中断号的过程称为中断源识别。如果中断请求来自CPU内部,CPU内有相应机制可以取到内中断请求的中断号;如果是不可屏蔽外中断请求,系统只安排了唯一的中断号(2号);当中断请求来自CPU的INTR外引脚时,情况就比
32、较复杂了。 6中断优先级中断优先级 由于8088共支持256个中断源,尤其是包括若干硬中断源,各种中断源就有同时提出中断请求的可能。当多个中断申请同时送到8088时,CPU必须能分别轻重缓急妥善处理。CPU分辨各中断源优先次序的方式是预先把所有中断源进行分级,称为中断优先级。当CPU遇到同时有两个或两个以上的中断申请时,就按它们的优先级次序,先为级别最高的中断源服务。 8088把所有中断源划分为4个等级,以0级为最高,依次降低等级。各中断源的等级划分情况是: 0级 除单步中断以外的内中断源; 1级 不可屏蔽外中断源; 2级 可屏蔽外中断源; 3级 单步中断。 不同级别中的两个中断源同时申请中断
33、时,CPU可以根据级别高低决定服务的先后次序。但同级中的两个中断源同时申请又如何处理呢?在0级中断源中,所有中断源由CPU执行指令产生的,只有执行DIV或IDIV指令时才有可能产生0号中断请求,执行一条中断指令只能产生一个中断号,而CPU在任何时刻只能执行一条指令,所以不可能同时有两个或两个以上的0级中断请求。1级与3级中断源分别各有一个,不涉及同时产生中断请求的问题,只有2级比较麻烦。 所有可屏蔽外中断源都处于中断优先级中的2级,这些外中断源都必须通过CPU的INTR引脚向CPU提出中断申请,如果它们当中出现同时申请的现象,将由中断控制器处理。在8088系统中,中断控制器可以把它管辖的所有可
34、屏蔽外中断源再进行内部分级,当同时出现多个中断申请时,由中断控制器判别相互间优先级的高低,并把其中最高级别的可屏蔽中断请求通过INTR送达CPU。 7中断屏蔽中断屏蔽 如果某个中断源发出中断请求后,CPU置之不理,继续完成自己的工作,这种现象称为中断屏蔽。8088系统中对各种中断分类处理,0级和1级中断是不能被屏蔽的,当CPU收到0级或1级中断请求时,必须立刻放下正在执行的程序进行中断处理;但2 级或3级中断就有被屏蔽的可能。3级中断是否屏蔽由标志寄存器中的TF标志位决定,当TF0时,CPU将不响应单步中断请求。指令系统中没有专门指令可以直接针对TF标志位操作,但可以通过PUSHF和POPF指
35、令达到修改TF值的目的。2级中断是否屏蔽受两个方面的控制:一是标志寄存器的IF标志位,如果IF0,所有的2级中断源都被屏蔽;另一个可控制2级中断屏蔽的是中断控制器,中断控制器是作为8088系统的一个外设,CPU可以通过命令的形式通知中断控制器屏蔽掉几号中断请求,这种方式可以只屏蔽2级中断源中的某几个而不是屏蔽所有2级中断。 8中断服务程序中断服务程序 CPU响应中断就是暂停正在执行的程序,转而为中断源进行相应的服务,称为中断服务。中断服务当然是通过执行一段程序来实现的。CPU响应某个中断时去执行的程序称为“中断服务程序”或“中断处理程序”。显然,如果要系统正常工作,中断服务程序就必须长期保存在
36、内存中,保证CPU随时可以执行它。CPU在两种情况下会转去执行中断服务程序,一是正在执行的程序中遇到了一条中断指令(INT指令),二是硬中断源产生了中断请求且没有被屏蔽。第二种情况是由硬件中断源引起的中断,也就是说,不需要CPU去执行什么专用指令,只要出现没被屏蔽的硬中断申请,就会导致CPU去执行相应的中断服务程序。 各个中断源都对应地有自己的中断服务程序,当机器启动完成后,这些中断服务程序是操作系统或ROM BIOS中的程序段。这些中断服务程序也是可以修改的,只要用户程序能够把一段程序长期保留在内存中(即常驻内存),并且通知CPU这就是某个中断的中断服务程序。 9中断向量中断向量 既然每个中
37、断服务程序都放在内存中,当然就有其入口地址,这样,当CPU响应中断时才能知道转到哪里去执行中断服务程序。入口地址是一个完整的逻辑地址,包括16位的段地址和16位的偏移地址,由总共32位数据构成,需要占据4个字节的存储空间。把中断服务程序的入口地址的各个字节按照一定的规则排列起来,构成的一个有特定含义的数据组合称为“中断向量”或“中断矢量”。8088系统规定其中断服务程序入口地址的4个字节的排列规则是: (偏移地址低字节,偏移地址高字节,段地址低字节,段地址高字节) 为了说明的方便,中断向量通常都用十六进制书写。比如某中断服务程序的入口地址在F000:EF05处,表示成中断向量就是: (05,E
38、F,00,F0) 10中断向量表中断向量表 8088系统中共有256个中断源,每个中断源都有自己的中断向量,把所有这些中断向量集中起来,按照中断号由0到255的顺序,从内存物理地址为0处开始依次存放,构成一张“中断向量表”。每个计算机系统的中断向量表都有自己固定的位置和长度,8088系统是把这张表放在内存的最低端,共占用1024个字节。图8.4是中断向量表的示意图。00000 0号中断服务程序偏移地址低字节00001 0号中断服务程序偏移地址高字节00002 0号中断服务程序段地址低字节00003 0号中断服务程序段地址高字节00004 1号中断服务程序偏移地址低字节00005 1号中断服务程
39、序偏移地址高字节00006 1号中断服务程序段地址低字节00007 1号中断服务程序段地址高字节00008 2号中断服务程序偏移地址低字003FF 0FFH号中断服务程序段地址高字节 11中断嵌套中断嵌套 在CPU执行一个低级别的中断服务程序时,如果系统中又产生了一个高级别的中断请求,这时系统会暂停低级中断服务,优先处理高级别中断,处理完后再继续低级中断服务。这种高级别中断打断低级别中断服务的现象称为中断嵌套。 中断嵌套的典型例子是,在一个中断服务程序中,需要在屏幕上显示一些信息,屏幕显示需要用到后面将要说明的10H号中断调用,因此在中断服务程序中就会写有INT 10H指令。这是一条内中断调用
40、指令,是最高级别的中断,在执行到该指令时,系统会转去先进行10H号中断服务,在屏幕上进行显示,10H号中断返回后,再继续原先低级别的中断服务。 8.4.2 中断处理过程中断处理过程 不论是软中断还是硬中断,当CPU响应中断时,自动完成下列操作: (1)取中断号n(中断源识别)。 (2)把标志寄存器(PSW)的内容入栈。 (3)当前CS的值入栈。 (4)当前IP的值入栈。 (5)把标志寄存器中的IF和TF标志位清0。 (6)从物理地址4n处取出4个字节的n号中断的中断向量,设取出的数据依次是b0、b1、b2、b3,把(b1, b0)拼成一个字型数据送到IP中,(b3, b2)拼成一个字型数据送到
41、CS中。 (7)按)按CS:IP的新值继续执行。的新值继续执行。 这些操作是由硬件自动完成的,是CPU响应中断这一过程中密不可分的几个步骤,不能把它们拆开来,理解作依次执行几条指令的结果。响应中断的过程中,有三个字型数据被入栈保护,其中包括CS和IP。CS与IP的专职就是存放下一条指令的逻辑地址,它们的值被入栈保护,就意味着将来可以从栈中取出保存的值,恢复被中断的程序继续执行,就像子程序调用与返回一样。 响应过程中的第(6)个操作是把CS和IP修改为n号中断向量的值,也就是把CS和IP改为n号中断服务程序的入口地址,继而转入中断服务程序执行。当中断服务完成后,在服务程序的最后有一条特别的指令I
42、RET作为结束。该指令将把中断时入栈保存的三个字型数据分别恢复到原出处,使CPU从中断服务程序转回到中断时的程序继续执行。 8.4.3 与中断有关的指令与中断有关的指令 在中断的有关概念描述中多次提到软中断是CPU执行中断指令时产生的中断,除了中断指令外,中断服务程序结束时也需要执行一条特殊的指令,以告诉CPU中断服务到此为止。关于2级中断的屏蔽标志位IF还有两条专用指令,分别说明如下。 【指令格式】INT n 【功能】产生一次n号中断请求。由于这是中断指令,属于内中断,具有最高级别,CPU必然响应,因此该指令将导致一次n号中断处理过程。具体的操作见8.4.2节中的中断响应时硬件自动完成的动作
43、。 【说明】【说明】 (1)指令格式中的n是一个立即数,用以代表中断号,有效范围是0到255。 (2)这是一条放在用户程序中的指令,与随时可能发生的硬件中断不同,这是程序员有意识地安排在程序中的一个中断,因而程序员很清楚这个中断指令执行的效果。这样使用的中断,其服务程序往往是系统预先编写好的一些专用子程序,完成一些特定的服务功能,供用户程序使用,就比如DOS提供的服务程序让用户程序以INT 21H指令去调用一样。这类程序段与子程序不同的是,它们在系统启动时就已进入内存中,不需要像子程序那样与调用它的程序相联接。因此,习惯上又把这类程序段称为中断服务子程序,当作子程序一样使用,只是调用方式不同而
44、已。 (3)指令格式中的n只要求在0到255之间,没有其它的限制。也就是说,不论是哪一个中断源,包括应该由硬件引起的外中断源,只要知道它的中断号,就可以用一条INT指令产生一次中断调用。但对硬件中断对应的0号、8号到0FH号,以及70H到 77H号,用INT指令去调用可能产生一些意想不到的结果,也有可能造成死机。 【指令格式】IRET 【功能】从栈中弹出3个字,第1个弹出的送到IP,第2个到CS,第3个到PSW。 【说明】这是专门为中断服务程序设计的一条指令,通常是中断服务程序的最后一条指令,它的功能与中断响应时硬件自动完成的动作相对应,从而保证不论是硬中断还是软中断,在中断服务结束后,CPU
45、都能回到正确的位置继续执行。 【指令格式】CLI 【功能】把标志寄存器的IF标志位清0,使CPU不响应可屏蔽外中断。 【指令格式】STI 【功能】把标志寄存器的IF标志位置1,允许CPU响应可屏蔽外中断。 CLI与STI指令总是配合使用,使得计算机系统在某一段时间内不响应任何可屏蔽外中断请求。CLI是屏蔽掉所有2级中断的简单方法,但在应用时请小心,如果用户程序执行过程中屏蔽了所有2级中断,将使得系统不能从键盘、鼠标等输入设备上接收数据,这将使操作人员失去对机器的控制。所以,总是在屏蔽2级中断一段时间以后再把它打开。在程序中屏蔽中断的一个很好的理由,是不想要自己的程序在需要连续执行时被硬件服务打
46、断,这通常是用在程序中需要执行一些不能暂停的任务的情况下。 8.4.4 系统提供的中断服务子程序系统提供的中断服务子程序 当计算机启动成功之后,内存中已经存放了很多具有固定功能的子程序,操作系统DOS提供的以INT 21H的形式调用的子程序只是其中的一部分,还有一部分是BIOS中断服务子程序,以及已装载的程序所提供的功能。 DOS提供的中断服务子程序分成很多子功能,完成各个子功能的程序段都集中放在一起,并且有一个总控程序,构成了一个整体。整个中断服务子程序的入口地址放在了21H号中断向量中。这是一个软件中断,调用方式是INT指令,并规定调用时AH中必须放子功能号,不同的子功能还需要有不同的入口
47、参数。前面章节中已经讲述了其中的1号、2号、9号、0AH号和4CH号子功能,实际上DOS提供给用户程序使用的子功能很多,包括如何读写文件、如何申请和释放内存、如何修改中断向量、如何取得及修改系统当前的日期和时间等等,不能一一列举。 BIOS是固化在计算机的内存ROM芯片中的程序,其中包括计算机启动时最初执行的一些程序,从设备自检、系统初始化,到引导操作系统。BIOS中还有很大一部分是提供了一些可供用户程序使用的中断服务子程序,这些子程序都用于对外部设备的直接控制,主要涉及键盘、显示器、打印机、串行通讯等,由于这些设备的控制方法比较复杂,如果让应用程序直接用输入输出命令去控制,就会给程序的编制带
48、来巨大的障碍。而这些设备的控制程序虽然较长,但都有一个固定的模式,适合于做成公共子程序的形式供各个程序调用,BIOS中就是存放着这样的子程序。各个主要的输入输出设备都有相应的子程序,这些子程序分在了各个中断服务程序当中,包括10H、14H、16H、17H号等几个中断。 8.4.5 中断与子程序的比较中断与子程序的比较 子程序是程序设计的一种常用方法,一般是把具有固定功能、在程序中无规律重复使用的程序段做成子程序,在需要的地方调用;中断是计算机系统支持的一种重要功能,当发生中断时,系统执行一段特定的程序。根据中断源的不同,需要把中断分为软件中断与硬件中断分别看待,软件中断、硬件中断与子程序之间有
49、一些共同之处: (1)都需要相应程序段的支持。发生子程序调用时,系统转去执行一段子程序,并在执行完后返回调用处继续执行;发生中断时,系统也是转去执行一段中断服务程序,执行完后返回中断点继续执行。被调用的程序段一定要在内存中。 (2)软件中断与子程序都由特定指令调用。软件中断由指令INT n调用,子程序调用指令是“CALL 子程序名”。不论是中断还是子程序调用,都会使系统修改CS和IP从而实现转向。 (3)发生调用时,系统自动记载返回地址。不论是中断还是子程序调用,系统在转入子程序/中断服务程序之前,都会把返回地址(IP或者是CS和IP)入栈保存。调用完成后,正是根据栈中保存的值,才能返回到正确
50、的位置。 (4)软件中断和子程序都可以带有入口参数和出口参数。由于软件中断和子程序都是具有固定功能的服务性程序段,都是按固定模式进行数据处理,通常,在调用前需要知道被处理的数据是什么或在什么地方,即入口参数,调用后又需要把数据处理的结果通知调用者,即出口参数。 (5)可以用子程序调用代替软件中断的调用指令。INT指令与FAR类型子程序调用的CALL指令之间的主要差别在于是否把标志寄存器入栈,因此,只要能够先把标志寄存器入栈保存,再用CALL指令同样可以进行软件中断服务子程序的调用。比如,下面的方法完全可以代替INT 21H指令: MOVBX,0MOVDS,BX;中断向量表的段地址MOVBX,8