中断就是打断处理器当前的执行流程,去执行另外一些和当前工作不相干的指令,执行完之后,还可以返回到原来的程序流程继续执行。
外部硬件中断顾名思义,外部硬件中断,就是从处理器外面来的中断信号。当外部设备发生错误,或者有数据要传送(比如,从网络中接收到一个针对当前主机的数据包),或者处理器交给它的事情处理完了(比如,打印已经完成),它们都会拍一下处理器的肩膀,告诉它应当先把手头上的事情放一放,来临时处理一下。
外部硬件中断是通过两个信号线引入处理器内部的。这两根线的名字叫NMI和INTR.
1. 非屏蔽中断中断不会被阻断和屏蔽的,称为非屏蔽中断(Non Maskable Interrupt,NMI),产生中断的设备,称为中断源。在传统的兼容模式下,NMI的中断源通过一个与非门连接到处理器。处理器的NMI引脚是高电平有效的,而中断信号是低电平有效的。当不存在中断信号的时候,与非门的所有输入都是为高,因为处理器的NMI引脚为低电平,这意味着没有中断发生。
当有任何一个非屏蔽中断产生时,与非门的输出都为高,Intel处理器规定,NMI中断信号由0跳变到1后,至少要维持4个以上的时钟周期才算有效,才能被识别。在实模式下,NMI被赋予了统一的中断号2,不会再细分。
2. 可屏蔽中断可屏蔽中断是通过 INTR 引脚进入处理器内部的,像 NMI 一样,不可能为每一个中断源都提供一个引脚。而且,处理器每次只能处理一个中断。在这种情况下,需要一个代理,来接受外部设备发出的中断信号。还有,多个设备同时发出中断请求的机率也是很高的,所以该代理的任务还包括对它们进行仲裁,以决定让它们中的哪一个优先向处理器提出服务请求。其中用的最多的就是中断代理就是8259芯片又叫可编程中断控制器(Programming Interrupt Controller,PIC)。
Intel处理器允许256个中断,中断信号的范围是0~255,8259负责提供其中的15个,但中断号并不固定。该中断控制芯片有自己的端口号,可以像访问其他外部设备一样用in和out指令来改变它的状态,包括引脚中的中断号。
8259芯片是 级联(Cascade) 关系,每片中只有8个中断输入引脚,主片的代理输出INT直接送到处理器的INTR引脚,从片的INT输出送到主片的引脚2上。
在 8259 芯片内部,有中断屏蔽寄存器(Interrupt Mask Register,IMR),这是个 8 位寄存器,对应着该芯片的 8 个中断输入引脚,对应的位是 0 还是 1,决定了从该引脚来的中断信号是否能够通过 8259 送往处理器(0 表示允许,1 表示阻断)。当外部设备通过某个引脚送来一个中断请求信号时,如果它没有被 IMR 阻断,那么,它可以被送往处理器。注意,8259芯片是可编程的,主片的端口号是 0x20 和 0x21,从片的端口号是 0xa0 和 0xa1,可以通过这些端口访问 8259 芯片,设置它的工作方式,包括 IMR 的内容。
中断能否被处理要看处理器,处理器内部有一个标志位IF,这就是中断标志(InterruptFlag)。当 IF 为 0 时,所有从处理器 INTR 引脚来的中断信号都被忽略掉;当其为 1 时,处理器可以接受和响应中断。IF 标志位可以通过两条指令 cli 和 sti 来改变。这两条指令都没有操作数,cli(CLear Interrupt flag) 用于清除 IF 标志位,sti(SeT Interrupt flag) 用于置位 IF 标志。
当中断发生频发时,8259 芯片会记住它们,并按一定的策略决定先为谁服务。总体上来说,中断的优先级和引脚是相关的,主片的 IR0 引脚优先级最高,IR7引脚最低,从片也是如此。当然,还要考虑到从片是级联在主片的 IR2 引脚上。
最后,当一个中断事件正在处理时,如果来了一个优先级更高的中断事件时,允许暂时中止当前的中断处理,先为优先级较高的中断事件服务,这称为中断嵌套。
实模式下的中断向量表
在实模式下,处理器要求将它们的入口点集中存放到内存中从物理地址0x00000开始,到0x003ff结束,共1KB的空间内,这就是所谓的中断向量表(Interrupt Vector Table,IVT)。
和可屏蔽中断不同,NMI 发生时,处理器不会从外部获得中断号,它自动生成中断号码 2,其他处理过程和可屏蔽中断相同。
实时时钟,CMOS RAM 和 BDC编码在外围设备控制芯片ICH内部,集成了实时时钟电路(Real Time Clock,RTC)和两小块由互补金属氧化物(CMOS)材料组成的静态存储器(CMOS RAM)。实时时钟电路负责计时,而日期和时间的数值则存储在这块存储器中。实时时钟是全天候跳动的,即使是在你关闭了计算机的电源之后,原因在于它由主板上的一个小电池提供能量。它为整台计算机提供一个基准时间,为所有需要时间的软件和硬件服务。
日期和时间信息是保存在 CMOS RAM 中的,通常有 128 字节,而日期和时间信息只占了一小部分容量,其他空间则用于保存整机的配置信息,比如各种硬件的类型和工作参数、开机密码和辅助存储设备的启动顺序等。这些参数的修改通常在 BIOS SETUP 开机程序中进行。
RTC 芯片由一个振荡频率为 32.768kHz 的石英晶体振荡器(晶振)驱动,经分频后,用于对CMOS RAM 进行每秒一次的时间刷新。常规的日期和时间信息占据了 CMOS RAM 开始部分的 10 字节,有年、月、日和时、分、秒,报警的时、分、秒用于产生到时间报警中断,如果它们的内容为 0xC0~0xFF,则表示不使用报警功能。
CMOS RAM的访问,需要通过两个端口来进行。0x70或者0x74是索引端口,用来指定CMOS RAM 内的单元。0x71或者0x75是数据端口,用来读写响应单元里的内容。举个例子,以下代码用于读取今天是星期几:
mov al,0x06
out 0x70,al
in al,0x71
端口0x70的最高位(bit 7)是控制NMI中断的开关。当它为0时,允许NMI中断到达处理器,为1时,则阻断所有的NMI信号,其他7个bit,即0~6位,则实际上用于指定CMOS RAM单元的索引号。
单元0x0a~0x0d不是普通的储存单元,而是4个索引寄存器(8位寄存器)的索引号,也是通过0x70和0x71访问的,这4个寄存器用于设定实时时钟电路的参数和工作状态。
寄存器 A 和 B 用于对 RTC 的功能进行整体性的设置,它们都是 8 位的寄存器,可读可写,其各位的用途如表:
寄存器 C 和 D 是标志寄存器,这些标志反映了 RTC 的工作状态,寄存器 C 是只读的,寄存器D 则可读可写,它们也都是 8 位寄存器,其各位的含义如表所示。特别是寄存器 C,因为 RTC 可以产生中断,当中断产生时,可以通过该寄存器来识别中断的原因。
内部中断发生在处理器,是由执行的指令引起的。内部中断不受标志寄存器IF位的影响,也不需要中断识别总线周期,它们的中断类型是固定的,可以立即转入相应的处理过程。
软中断软中断是由int指令引起的中断处理。这类中断也不需要中断识别总线周期,中断号在指令中给出。
最有名的软中断是BIOS中断,之所以称为BIOS中断,是因为这些中断功能是在计算机加电之后,BIOS程序执行期间建立起来的,这些中断功能在加载和执行主引导扇区代码之前就可以使用了。
BIOS 可能会为一些简单的外围设备提供初始化代码和功能调用代码,并填写中断向量表,但也有一些 BIOS 中断是由外部设备接口自己建立的。
首先,每个外部设备接口,包括各种板卡,如网卡、显卡、键盘接口电路、硬件控制器等,都有自己的只读存储器(Read Only Memory,ROM),类似于 BIOS 芯片,这些 ROM 中提供了它自己的功能调用例程,以及本设备的初始化代码。按照规范,前两个单元的内容是 0x55 和 0xAA,第三个单元是本 ROM 中以 512 字节为单位的代码长度;从第四个单元开始,就是实际的 ROM 代码。
在计算机启动期间,BIOS 程序会以 2KB 为单位搜索内存地址 C0000~E0000 之间的区域。当它发现某个区域的头两个字节是 0x55 和 0xAA 时,那意味着该区域有 ROM 代码存在,是有效的。接着,它对该区域做累加和检查,看结果是否和第三个单元相符。如果相符,就从第四个单元进入。这时,处理器执行的是硬件自带的程序指令,这些指令初始化外部设备的相关寄存器和工作状态,最后,填写相关的中断向量表,使它们指向自带的中断处理过程。