✅ 通过对 【计算机与UNIX汇编原理 ① ~ ⑫】的学习,我们已经大致掌握了汇编程序设计的相关知识
接下来,我将其分栏名改为 【计算机原理与接口技术(UNIX) 】,重点将放在 “计算机原理与接口技术” 上
interrupt ☀️
上一篇文章链接:【计算机原理与接口技术(UNIX)⑮】——输入/输出系统【查询方式、中断控制方式、DMA 、8237A】.
下一篇文章链接:【计算机原理与接口技术(UNIX)⑰】——微型计算机系统的串行通信 [ 8250 + 具体样例 + 上机实验].
● 中断技术是现代计算机系统中非常重要的功能。最初,中断技术引入计算机系统,只是为了解决快速的 CPU 与慢速的外设之间传送数据的矛盾。随着计算机技术的发展,它不断被赋予新的功能——>计算机故障检测、多道程序分时操作等,接下来我们就会对其进行学习。
● 这里的中断技术可以理解为上一节 “中断控制方式” 的升级展开版 (上一篇文章)。
● 中断:CPU 在执行程序的过程中,由于某种外部或内部事件的作用,使 CPU 停止当前正在执行的程序而转去为该事件服务,待事件服务结束后,又能自动返回到被中断程序进行执行的过程。
● 对中断流程图说明:
① 被中断的原程序称为主程序。
② 中断处理程序称为中断服务子程序。
③ 主程序被中止的地方,称为断点,也就是下一条指令所在内存的地址。
● 温固一下(上一篇文章中的 “中断控制方式”)它的详细执行流程:
● 说明:
[1] ①和②在初始化时都是 “打开”。
[2] 输入设备数据准备好后,进行③(发出输入选通信号,并将数据写入接口)
[3] 然后。输入接口会向 CPU 进行④(发出中断请求)
[4] CPU 收到中断请求后,会进行⑤(回复中断响应,表示 CPU 准备好了)
[5] 然后,CPU 就进行⑥(转而执行中断服务子程序)
[6] 接着,输入接口就会把接口里的数据收过来(即⑦)
[7] 最后,完成一次数据输入操作后,执行⑧(最后返回到①)
● 中断源:能够引发中断的事件,即发出中断请求的来源。(中断源可以是外部事件,也可以是 CPU 内部事件)
● 外部中断源举例:
① I/O设备 —— 如键盘、显示器、打印机
② 数据通道 —— 如磁带、磁盘
③ 时钟 —— 如8254 0#,由此引发的中断
④ 故障源 —— 如掉电、存贮器奇偶校验错
● 内部中断源举例:
① 执行INT
软件中断指令 —— 如执行指令INT 21H
【 注意,这里的 21H 是一个数,后面还会出现另一个”21H“,留个神】
② CPU指令执行产生的异常 —— 如被0
除、单步执行
● 根据中断源的不同,中断可被分为:外部中断和内部中断。
● 外部中断:由外部事件引发的中断,即由 CPU 以外的设备发出,并由 CPU 的中断请求信号引脚输入所引发的中断。(也被称为硬件中断)
● 80X86 CPU有2
个引脚(INTR
和NMI
)可以接收外部的中断请求信号。由输入到INTR
引脚的中断请求信号引发的中断称为可屏蔽硬件中断。由输入到NMI
引脚的中断请求信号引发的中断称为非屏蔽硬件中断。( INTR、NMI 这个要记住,后面常提到这个)
● 内部中断:由 CPU 内部事件,即由 CPU 硬件故障或程序执行中的事件所引发的中断称为内部中断。内部中断可以进一步分为软件中断和异常。
● 软件中断:执行有定义的INT n;
指令而引发的中断。软件中断可分为BIOS中断、DOS中断。DOS中断,又分为 DOS 专用中断、DOS保留中断,用户可调用的DOS中断以及保留给用户开发的中断。
● 异常:由于 CPU 本身故障、程序故障等引发的中断。 异常有进一步可分为故障(Fault
)、陷阱(Trap
)、中止(Abort
)。这三个作了解即可。
● 中断类型码:为了区别这些不同的中断,微机系统给每一个中断分配的一个中断号n
。其取值范围是0~255
。
● 微机系统可以处理256
种中断。在这256
个中断中,intel 在它各种微处理器中都保留了前32
个(0~31
)为系统所专用,后224
个可由用户设定。
● 常用中断号所对应的中断如下:
① 0型中断 —— 除法错中断
② 1型中断 —— 单步或陷阱中断
③ 2型中断 —— 非屏蔽硬件中断
④ 3型中断 —— 断点中断
⑤ 4型中断 —— 溢出中断
⑥ 5型中断 —— 屏幕打印
⑦ 08H~0FH
型中断 —— 可屏蔽硬件中断(08H 这个多记记)
⑧ 10H~1FH
型中断 —— BIOS中断(1CH 留点儿印象)
⑨ 20H~3FH
型中断 —— DOS中断(20H、21CH 多记记)
● 中断向量:在实模式下,中断向量是中断服务子程序的入口地址。
● 中断向量的构成:每个中断号所对应的中断向量占4
字节,它由2
部分组成:服务程序所在代码段的段基址(前2
个字节)、服务程序入口的偏移地址(后2
个字节)。其存放规律如下:
● 中断向量表:在实模式下,系统存储器地址空间中,最低的1KB
空间,即00000H~003FFH
单元依次存放着256
个中断号所对应的中断向量(每个中断对应的中断向量占4
字节),存放这个1024
字节的中断向量的存储区域就是一张中断向量表。如下图所示:
● 举例:①求08H
型中断向量存放在何处?②若已知系统 RAM 的 20H~23H 单元的内容依次为 22H、33H、44H、55H,则08H
型中断服务子程序入口的物理地址为?
①解:∵ 08H × 4 = 0000 1000B × 0100B = 0000 1000 00B = 20H (乘 4 相当于整体左移两位)
∴ 08H 型中断向量存于 20H~23H 单元中②解:该物理地址 = 5544H × 16 + 3322H = 55440H + 3322H = 58762H
● 中断向量表的初始化:
① 由 BIOS 设计的中断服务程序(如INT 16H
, INT 10H
…),它的中断向量在加电时由 BIOS 负责写入中断向量表。
② 由 DOS 设计的中断服务程序(如INT 21H
),它的中断向量是在启动 DOS 时,由 DOS 负责写入中断向量表。
③ 用户程序开发的中断服务程序,由用户程序写入其中断向量。
● 样例:设n
型中断服务程序的名字是SERVICE
,如何将SERVICE
的入口地址写入对应的中断向量表呢?方法如下:【方法二的在后面编程中常用到,对25、35这两个数要有感觉】
方法一: 用户自己编写程序填写中断向量
CLI ; I标志清零
PUSH DS ; 压入段基址(保护)
MOV AX, 0000H
MOV DS, AX ; 基地址是 0000H, 可自行设定
MOV BX, 4*n ; 偏移地址是 4*n
MOV AX, OFFSET SERVICE
MOV [BX], AX ; 将服务程序入口偏移地址写入 4*n ~ 4*n+1 单元
MOV AX, SEG SERVICE
MOV [BX+2], AX ; 将服务程序段基址写入 4*n+2 ~ 4*n+3 单元
POP DS ; 弹出段基址(恢复)
STI
;-----------------------------------------------------
方法二: DOS设计 2 个子程序,专门用于中断向量的读出、写入
[ INT 21H 的35H子功能 ]
功能: 读出 n 型中断向量
入口: AL = 中断类型码
出口: ES:BX = n型中断向量
[ INT 21H 的25H子功能 ] <----这道例题只会用到这个
功能: 写入 n 型中断向量
入口: DS = 中断服务程序所在代码段的段基址
DX = 中断服务程序入口的偏移地址
AL = 中断类型码
出口: 无
采用方法二, 对应的程序段如下:
CLI
PUSH DS
PUSHA ; 用于“保护现场”
MOV AX,SEG SERVICE
MOV DS,AX
MOV DX,OFFSET SERVICE ; 获取 中断服务程序入口的偏移地址 到 DX
MOV AH,25H ; 写入 n 型中断向量, 这时需要用户进行键盘输入
MOV AL,n
INT 21H ; 执行该 n 型中断
POPA ; 用于“恢复现场”
POP DS
STI
● 微机系统中断中的各种类型中断的响应和处理过程不完全相同,主要区别在于中断类型码的获得方式不同,当 CPU 获得了中断类型码后的处理过程基本类似。
① 对于非屏蔽硬件中断请求,CPU 内部会自动产生中断类型码。
② 对于可屏蔽硬件中断请求,当 CPU 处于开中断状态时,由外部中断控制器将相应的中断类型码送给 CPU。
③ 对于异常,中断类型码也是自动形成的。
④ 对于INT n
指令,中断类型码即为指令中给定的n
。
● CPU 获得了中断类型码n
后,中断的处理过程如下:
① F寄存器(状态寄存器) → 堆栈(目的:保存INT n
之前的各个标志位状态)
② 使 F 中的 T 标志置 0 → 禁止单步操作,使 I 标志置0
→ CPU处于关中断状态(目的:清除 I 标志和 T 标志,屏蔽新的可屏蔽硬件中断和单步中断)
③ 将主程序断口地址 → 堆栈(目的:保护主程序的断点。细节:先压入断口的段基址 CS,再压入断口的偏移量 IP)
④ CPU 从4n~4n+3
单元取出n
型服务程序入口地址 → CS:IP(目的:转入n
型中断服务程序。细节:4n~4n+1单元的内容 → IP,后两个单元的内容 → CS)
⑤ CPU 根据新的 CS:IP 的值转向相应的n
型中断服务子程序。
⑥ 当服务子程序执行完毕,执行中断返回指令。中断返回指令的功能是按顺序恢复断点处的 IP 值、CS 值和之前保护的相应中断前的标志寄存器内容 → 标志寄存器。
⑦ CPU 根据恢复后的 CS:IP 的值返回到断点,继续执行主程序。
● 从上述过程可发现:当 CPU 获得中断类型码后,在中断向量的引导下,CPU 即可执行相应的中断服务子程序。中断向量引导作用示意图如下:
● 说明:在上图中的 “①②③④” 分别对应 “中断的处理过程” 的相应步骤,对照着看更清晰。注意其中的 “NEXT
”是一个程序名。
● 中断服务子程序的结构:【后面敲的代码也是这个结构】
ISR PROC
保护现场
中断处理
恢复现场
中断返回
ISR ENDP
● 中断优先级:当有多个中断源在同一时刻提出请求时,CPU 对中断响应的次序。
● 中断响应的次序是用排队器硬件实现的,中断优先级如下图所示。可以根据需要,由程序控制改变实际的中断处理次序。
"80X86响应中断的优先级如下:"
中断类型 优先级
除法错中断 最高
软件中断INT n ↓
断点中断 ↓
溢出中断INTO ↓
NMI中断 ↓ ; 硬件中断
INTR中断 ↓ ; 硬件中断
单步中断 最低
● 禁止中断:产生中断请求后,CPU 不能中断现行程序的执行。
● 中断屏蔽:使程序有选择地封锁部分中断,而允许其余部分仍可能够响应(即能够响应中断请求)。
● 中断嵌套:在执行中断服务程序时,仍可再响应中断申请。(类似与 C 语言的函数嵌套)
① 对于硬件中断,接口电路应具备 “屏蔽” 和 “开放” 的功能,这种功能由程序员通过软件去控制。
② 能实现中断判优(中断排队)。即当有多个中断源提出请求时,应能优先响应高级别的中断源。
③ 能够实现中断嵌套。
④ 响应中断后,能自动转入中断处理,处理完毕能自动返回断点。
▶ STI
功能 :使 F 寄存器中I
标志置1
,CPU 处于开中断状态。
▶ CTI
功能 :使 F 寄存器中I
标志置0
,CPU 处于关中断状态。
■ 格式:INT n
● 说明:n
为中断类型码,是0~255
之间有定义的无符号整数。
▶功能:无条件转向n
型中断服务子程序。
● INT n
指令执行的详细过程:【即 CPU 响应软件中断的详细过程】
① F 寄存器 → 栈(保存INT n
之前的 F 状态)
② 使 F 中的T
标志置0
—— 禁止单步操作
③ 使 F 中的I
标志置0
—— CPU 处于关中断状态
④ 断口地址 → 栈(先:断口基地址(CS) →栈,后:断口偏移地址(IP)→栈)
⑤ CPU 从4n~4n+3
单元取出n
型服务程序入口地址 → IP:CS,从而转入n
型中断服务程序。
● 这个(即IRET
)就是 1.4 的那张图里面的紫色框里的东西。【IRET 这个指令,后面常用,这里加个记忆】
▶功能:依次从栈顶弹出6
个元素 → IP、CS、F。
● 说明:如果栈顶是INT n
的断口地址,则执行IRET
后,才能返回断点,否则不能。
● 执行INT n
指令和执行IRET
指令的堆栈操作示意图:
● 注意:存储地址是上低下高。若进程进行的是RET
,要分远程和进程两种情况,远程的RET
是:从栈顶弹出4
个元素 → IP、CS 即可。进程的RET
是:从栈顶弹出2
个元素 → IP 即可。【注: RET 这个指令,在 6.4 用户中断的代码里面才有出现】
▶功能:先判断 F 寄存器中O
标志位是否为1
,如是则直接调用类型为4
的中断子程序,用以处理溢出中断的情况(后续将会详细学到)。
● 由前面的学习可知,外部中断是由 CPU 以外的中断请求而引发的。而且 CPU 也只有一个引脚INTR
用来接收外部的可屏蔽硬件中断请求。
● 为了管理多个外部发来的中断源,Inter 公司设计了专门的配套芯片 “8259A 中断控制器”(我们将对其进行学习)。
① 1
片 8259A 中断控制器可以管理8
级外部中断(打个比方,把它比作进城收费ETC收费站,他可以同时开8
个车道,但是能也分级别),并最后向 CPU 提出中断请求。通过级联,采用 “1 主 8 从” 的方式,可扩展管理64
级中断。(1
个在前,8
个接在其后)
② 每一级中断都可以通过设置内部屏蔽字进行屏蔽或允许。(我们把 ”每一级“ 假想成 ”每一通道“ 可能好理解点)
③ 在中断响应周期,8259A 可以向 CPU 提供相应的中断向量。
④ 8259A 是很复杂的中断控制器,可以通过编程从中断触发方式、中断屏蔽方式、中断优先级管理方式、中断结束方式和总线连接5
个方面对中断进行管理。
● 8259A 的内部结构图:
① 中断请求寄存器(IRR):一个8
位的寄存器。IRR 的 D0 ~ D7 位分别对应着 IR0 ~ IR7 引脚
▶功能:寄存引脚 IR0 ~ IR7 的中断请求信号。(IRR 的 Di 位置为1
时,表明 IRi 引脚上有了中断请求信号 )
② 中断屏蔽寄存器(IMR):一个8
位的寄存器。IMR 的 D0 ~ D7 位分别对应着 IR0 ~ IR7 引脚。
▶功能:寄存程序员写入的中断屏蔽字。(屏蔽字某位 = 1 时,即 IMRi 位 = 1 时,则与该位对应的中断请求信号(IRR 的 Di 位)就不能送到中断优先权电路)
③ 优先权电路 (排队电路):一种控制电路。
▶功能:比较同时送达优先权电路的中断请求,哪一个级别最高。然后通过判优 “选中” 其中级别最高的中断源,然后通过控制电路,从INT
端向 CPU 提中断请求。【注重对 INT 产生点记忆】
● 前三者之间的关系(即①②③之间的关系):
● 对上图的说明:“IRR 的 D0 ~ D7 位” 分别与 “IMR 的 D0 ~ D7 位的非” 相与。(比如,当 IMR 的 D0 = 1 时,则 IRR 的 D0 被屏蔽)
● 举例:
“样例一:”
MOV AL, 11111100B
OUT 屏蔽寄存器(IMR)的口地址, AL
;屏蔽 IRR7 ~ IRR2 的中断请求, 只开放 IRR1,IRR0 的中断请求
“样例二:”
IN AL, 屏蔽寄存器(IMR)的口地址
AND AL, 11110111B
OUT 屏蔽寄存器(IMR)的口地址, AL
;开放 IRR3 的请求, 对其它位的请求保持原状态
④ 中断控制电路:它是 8259A 内部的控制器。它有一组寄存初始化命令字(ICW1 ~ ICW4)的寄存器和一组寄存器操作命令字(0CW1 ~ 0CW3)的寄存器,以及相关的逻辑控制(开关)。
▶功能一:寄存一组初始化命令字和操作命令字,通过译码产生内部控制信号。
▶功能二:当判优电路选中一个中断源时,向 CPU 提中断请求 (INT
)
▶功能三:当通过 I N T A ‾ \overline{INTA} INTA 接收 CPU 送来的中断响应信号时,中断响应信号 I N T A ‾ \overline{INTA} INTA是2
个连续的负脉冲。
⑤ 中断服务寄存器(ISR):一个8
位的寄存器。ISR 的 D0 ~ D7 位与 IRR 的 D0 ~ D7 位一一对应。
▶功能:记录 CPU 正为哪一个中断源服务。(例如:通过判优电路 IRR 中 D0 位的请求被选中时,8259A 会向 CPU 发出中断请求,并通过 I N T A ‾ \overline{INTA} INTA 收到第一个中断响应信号后,ISR 的 D0 位将置1
,IRR 的 D0 位将置0
)【注重对 I N T A ‾ \overline{INTA} INTA 产生点记忆】
● 补充说明一:当 ISR 的 D0 位置1
时,表明 CPU 正在准备(或正在)执行 IR0 的(中断)服务(子)程序;反之,如果 ISR 的 D0 位由1
→0
时,表明 IR0 的中断服务程序执行完了。
● 补充说明二:所以 ISR 的每一位都是响应中断源的中断服务标志位。
⑥ 数据总线缓冲器:一个暂存数据的存储器。
▶功能一:完成与 CPU 数据线的配接
▶功能二:接收初始化命令字、操作命令字
▶功能三:当收到第二个中断响应脉冲时,通过它们向 CPU 送出被选中的中断源的中断类型码n
。在这之后,CPU 会从 4n+0~4n+3
单元取出n
型中断向量, 从而转入n
型服务程序。
⑦ 读写逻辑:一种控制读写的功能模块。
▶功能:接收片选信号 C S ‾ \overline{CS} CS、端口地址选择信号 A0 和读写控制信号 R D ‾ \overline{RD} RD、 W R ‾ \overline{WR} WR。
⑧ 级连/缓冲比较器
▶功能:一位 8259A 可以管理8
级中断,二片 8259A “级联” 可管理15
级中断,级连/缓冲比较器是为完成多片8259A
级联设置的模块。
● 补充说明一:级联应用时,8259A 一片主片最多可接8
片从片,扩展到64
级中断。
● 补充说明二:级联连接时,从片的INT
信号接主片的 IR0 ~ IR7 之一,并确定了在主片中的优先级,从片的 IR0 ~ IR7 接外设的中断请求信号,最终即可确定64
个优先级。
● 补充说明三:以级联方式工作时,主 8259A 的 S P ‾ / E N ‾ \overline{SP}/\overline{EN} SP/EN 接高电平,从 8259A 的 S P ‾ / E N ‾ \overline{SP}/\overline{EN} SP/EN 接低电平。由初始化命令字 ICW4 来设置缓冲方式或非缓冲方式。
● 8259A 是一个含有28
个引脚的双列直插式芯片,其外部引脚图如下:【先前让对 INT 、 I N T A ‾ \overline{INTA} INTA 多产生记忆,就是在这里体现,前面的是理论,下图就是物理实件,这两个端口引脚位置清晰可见】
● 8259A 的引脚信号可分为一下4
组:
① 与 CPU 总线相连的(引脚)信号:
[1] D0 ~ D7:(双向三态)数据线。(与 CPU 数据总线直接相连,或与外部数据总线缓冲器相连)
[2] W R ‾ \overline{WR} WR、 R D ‾ \overline{RD} RD:读写命令信号线,与 CPU 的读/写控制信号相连。
[3] CS:片选信号线,通常接 CPU 的高位地址总线或地址译码器的输出。
[4] INT:中断请求输出端。用于向 CPU 发出中断请求信号。
[5] I N T A ‾ \overline{INTA} INTA:中断响应输入信号。用于接收 CPU 发来的中断响应。
[6] A0:地址线。通常接 CPU 低位地址总线,A0 = 0 时是偶地址,A0 = 1 时是奇地址。该地址线与 W R ‾ \overline{WR} WR、 R D ‾ \overline{RD} RD信号配合,可读写 8259A 内部相应的寄存器,用于选择内部端口,对应图表如下:【注意对 偶地址、奇地址 产生点记忆】
② 与 CPU 总线相连的(引脚)信号:
IR0 ~ IR7:与外设的中断请求信号相连,通常 IR0 的优先权最高,IR7 的最低。
③ 级联信号:
[1] CAS0 ~ CAS2:级联信号线。主片为输出,从片为输入,与 S P ‾ / E N ‾ \overline{SP}/\overline{EN} SP/EN 配合来实现级联。
[2] S P ‾ / E N ‾ \overline{SP}/\overline{EN} SP/EN:主/从允许缓冲线。( 在缓冲工作方式中,用作输出信号,以控制总线缓冲器的接受( o v e r l i n e E N = 1 overline{EN}=1 overlineEN=1)和发送( o v e r l i n e E N = 0 overline{EN}=0 overlineEN=0)。当数据从 CPU 送往 8259A 时, S P ‾ / E N ‾ \overline{SP}/\overline{EN} SP/EN 输出为高电平;当反过来输送时为低电平。而在非缓冲工作方式中,它用作输入信号,表示该 8259A 是主片( S P ‾ = 1 \overline{SP}=1 SP=1)或从片( S P ‾ = 0 \overline{SP}=0 SP=0) )
④ 级联信号:
[1] VCC:接+5V
的电源。
[2] GND:接地线。
● 8259A 的中断过程就是(微型)计算机系统响应可屏蔽硬件中断的过程。我们举一个栗子来解释其工作流程。【初始情况如下图】
● 工作流程说明:
① 假设 IR0、IR6、IR7 上同时有3
个中断请求信号。则 IRR 的 D0、D6、D7 都会由0
变为1
。
② 因为 IMR 的 D0 = 0、D6 = 1、D7 = 0,则 IR0 和 IR7 上的中断请会被送到优先权电路,而 IR6 上的中断请求会被屏蔽。(在这之前,程序员事先已经将中断屏蔽字写入中断屏蔽寄存器 ——> 目的在于决定哪些中断请求能够送到优先权电路)
③ 假设 IR0 优先级高于 IR7,则排队结果选中 IR0 向 CPU 发出中断请求信号。(注:8259A 由INT
引脚向 CPU 发出信号)
④ 假如当前 CPU 满足响应可屏蔽中断的条件,则可响应 IR0 中断,并向 8259A 发送两个连续的脉冲信号。(8259A 从引脚 I N T A ‾ \overline{INTA} INTA收到信号)
⑤ 8259A 收到第1
个脉冲信号(中断响应信号)后,会使 ISR 的 D0 有0
变为1
,同时 IRR 的 D0 有1
变为0
。(注:8259A 从引脚 I N T A ‾ \overline{INTA} INTA收到信号)
⑥ 8259A 收到第2
个脉冲信号后(中断响应信号),会向 CPU 发送对应的中断类型码n
。
⑦ CPU 得到中断类型码n
(假设这里为08H)后,会在中断向量表中找到对应中断向量,转而执行对应中断服务(子)程序,在服务程序中对通过 IR0 提出中断请求的外设服务。(在实模式下,CPU 会从4×n~4×n+3
单元取出该中断源的中断向量 → IP、CS,从而引导 CPU 执行中断源对应的中断服务子程序)
⑧ 8259A 的 ISR 的 D0 会由1
变为0
,表示对来自 IR0 上的中断请求服务完毕。同时,CPU 在执行中断服务子程序的最后一条指令IRET
时,将返回被中断的程序继续原来的任务。当然,在这个例子中,在对 IR0 上的中断请求服务完成后,假如 8259A 的 IR7 上的中断请求仍然维持有效,则可以开始以同样的过程处理 IR7 的中断请求。
● 8259A 对中断的管理涉及多方面,每方面都有多种工作方式,如下图所示:
● 补充说明:用户可根据自己的需要,通过 8259A 初始化时写入初始化命令字和操作命令字来设置选择相应的工作方式。
● 边沿触发:IRi 出现上升沿表示有中断请求。
● 电平触发:IRi 出现高电平表示有中断请求。
● 常规屏蔽方式:IMR 屏蔽字决定了允许或禁止某位 IRi 所对应的中断:IMR 的 Di = 1表示禁止, Di = 0 表示允许。
● 特殊屏蔽方式:提供了允许较低优先级的中断能够得到响应的特殊手段。
▶原理:假定当前正在处理 IR6,先进入特殊屏蔽方式,然后设置 IMR 的 D6 = 1。这时,除 IR6 外的所有中断请求均能得到响应。
◆ 注意:特殊屏蔽方式中只能用SEOI
命令结束中断。
● 固定优先级方式:所有中断请求 IRi 的中断优先级固定不变,默认优先级顺序从高到低为 IR0 ~ IR7。
● 循环优先级方式:中断源轮流处于最高优先级,即自动中断优先级循环。当某中断请求 IRi 被处理后,其优先级别自动降为最低,原来比它低一级的中断上升为最高级。
● 中断嵌套方式的定义:在中断处理过程中允许被更高优先级的事件所中断称为中断嵌套。8259A 有如下两种中断嵌套方式。
● 普通全嵌套方式(默认方式):当某一中断正被处理时,只有更高优先级的事件可以打断当前的中断处理过程而被服务。
● 特殊全嵌套方式:当某一中断正被处理时,允许同级或更高优先级的事件可以打断当前的中断处理过程而被服务。
● 中断结束处理方式定义:当某一 IRi 中断被服务时,ISR 中的相应位 Di = 1。当服务结束后,则必须清零该 Di 位。注:使 ISR 中的 Di = 0 是通过向 8259A 发出中断结束命令(EOI
命令)实现的。
● 三种EOI
命令:
① 自动EOI(即自动EOI方式:AEOI
) —— 在第2
个 I N T A ‾ \overline{INTA} INTA结束时,由 8259A 使 ISRi 自动复位。因不保留当前正在服务的中断的状态,故AEOI
不能用于中断嵌套方式。【后面主要用这个,对AEOI
产生记忆即可】
② 非指定EOI(即正常EOI方式:NSEOI
) —— 由 CPU 发出正常EOI
命令,该命令将使 ISR 的 Di = 1 中优先级最高的那一位复位。用于普通全嵌套方式。
③ 指定EOI(即特殊EOI方式:SEOI
) —— 由 CPU 发出一条SEOI
命令,该命令中将指出所要复位的 ISR 的位号。用于特殊屏蔽方式。
● 对 8259A 的编程有两类命令字:初始化命令字 ICW1 ~ ICW4 和操作命令字 OCW1 ~ OCW4。
● 系统复位后,初始化程序对 8259A 置入初始化命令字 ICW。初始化后可通过发出操作命令字 OCW 来定义 8259A 的操作方式,来实现对 8259A 的状态、中断方式和优先级管理的控制。
● 虽然初始化命令字只发一次,但操作命令字允许重置,可以动态地改变 8259A 的操作和控制。
● 初始化命令字 ICW(Initialization Command Word)通常是系统开机时,由初始化程序填写,且在整个系统工作过程中保持不变。初始化命令字必须按顺序填写。
▶功能:
① 设定中断请求信号触发的方式。(即高电平触发还是低电平触发)
② 设定 8259A 的工作方式。(即单片或是级联)
③ 设定 8259A 的中断类型码。(即 IR0 对应的中断类型码)
④ 设定优先管理方式。
⑤ 设定中断结束方式。
● 对 8259A 编程初始化命令字共预置了4
个命令:ICW1、ICW2、ICW3、ICW4。
● 初始化命令字必须按顺序填写,但并不是任何情况下都要预置4
个命令字,应视情况而定。
● 8259A 有两个端口地址,由片选信号和端口选择线 A0 (它通常接至 CPU 地址线 A0)共同确定,A0 = 0 为偶地址端口,A1 = 1 为奇地址端口,各命令字写入的端口也有规定。【再次加强对 偶地址、奇地址 的影响】
① ICW1 —— 芯片控制初始化命令字,格式如下图所示:【这里是 偶地址,因为 A0 = 0】
● 样例:IBM/XT 系统中,在设置 8259A ICW1 的指令如下,其中 8259A 的偶地址为 20H。【 终于在这里出现了,在前面的提到的所有 20H、21H 都只单单是一个数,而这里出现的 20H 和后面出现的 21H 是一个“地址”】
MOV AL, 13H ; 13H = 0001 0111B
OUT 20H, AL
◆ 代码说明:表示该 8259A 为单片方式,上升沿触发,要求设置 ICW4。
② ICW2 —— 设置中断类型码初始化命令字,格式如下图所示:【这里是 奇地址,因为 A0 = 1】
◆ 对上图的说明:
[1] A0 = 1,ICW2 必须写到 8259A 的奇地址端口中。
[2] 8259A 中的 IR0 端对应的中断类型码为中断类型码基值,它是可以被8
整除的正整数。
[3] ICW2 的高5
位 D7 ~ D3 由用户设定。当 8259A 收到 CPU 发来的第二个 I N T A ‾ \overline{INTA} INTA 信号,它会向 CPU 发送中断类型码,其中高5
位为ICW2的高5
位,低3
位根据 IR0 ~ IR7 中断应该为哪一级中断(对应 000 ~ 111)来确定。
● 样例:IBM/XT 系统中,在设置 8259A ICW2 的指令如下,其中 8259A 的奇地址为 21H。【 刚刚说的 21H 就是这个,它指的是 21H 这个“地址”。为什么要这么弄,后面 5.3 有写】
MOV AL, 08H ; 08H = 0000 1000B = 00001 000B
OUT 21H, AL
◆ 代码说明:由于 D7 ~ D3 = 00001,所以对应8
个中断的类型码为08H~0FH
(刚好 8 个,假如是 00011 ,那么对应的是 3×8 ~ 3×8 +8,即24 ~ 32,即18H ~ 1FH)。如果当前响应的中断是 IR4 ,响应中断后 8259A 送出的中断类型码就是 0CH
(08H + 4H = 0CH)。
③ ICW3 —— 标识主片/从片初始化命令字,格式如下图所示:【这里是 奇地址,因为 A0 = 1】
◆ 注:在级联的时候才设置 ICW3。
● 样例:某 8259A 主片的 IR3、IR7 端连接了两个 8259A 从片,设主片 8259A 端口地址为 20H 和 21H;从片 1 的 8259A 端口地址为 A0H 和 A1H;从片 2 的8259A 端口地址为 80H 和 81H。请编写初始化命令字。
主片:
MOV AL, 88H
OUT 21H, AL ; 88H = 1111 1111B, 目的:全部引脚都允许
从片1:
MOV AL, 03H
OUT 0A1H, AL ; 第一个从片的中断请求输出端接到主片 8259A 的 IR3
从片2:
MOV AL, 07H
OUT 81H, AL ; 第二个从片的中断请求输出端接到主片 8259A 的 IR7
④ ICW4 —— 方式控制初始化命令字,格式如下图所示:【这里是 奇地址,因为 A0 = 1】
● 补充说明:当 ICW1 中的 IC4 = 1 时,要求预置 ICW4 命令字,对 80x86 系统必须预置 ICW4。
● 操作命令字 OCW(Operation Command Word): 用以规定 8259A 的工作方式,由 CPU 向 8259A 送出的三个字节。
▶常用功能:
① 决定中断屏蔽。
② 决定中断优先级次序。
③ 决定中断结束方式。
● 补充说明:操作命令字在设置时顺序上没有严格的要求。但端口地址有严格的要求,OCW1 必须写入奇地址端口,OCW2 和 OCW3 必须写入偶地址端口。
① OCW1** —— 中断屏蔽操作命令字,格式如下图所示:【这里是 奇地址,因为 A0 = 1】**
● 说明:命令字中的 M7 ~ M0 对应 IMR 的各位。Mi = 1 表示该中断被屏蔽,Mi = 0表示该中断开放。
② OCW2 —— 优先权循环方式和中断结束方式操作命令字,格式如下图所示:【这里是 偶地址,因为 A0 = 0】
● 对上图的说明:
① 上面的大致了解一下即可,后面我们最常用的是 “常规命令字20H
”。
② R、SL、EOI 的不同组合决定了 8259A 的几种工作方式。
③ L2 ~ L0 这几位确定当 SL = 1 时指定的特殊结束或特殊循环时的中断优先级。
③ OCW3 —— 特殊屏蔽方式和查询方式操作字,格式如下图所示:【这里是 偶地址,因为 A0 = 0】
● 说明:OCW3的功能有3
个,分别包括 设定特殊屏蔽方式、设置对 8259A 寄存器的读写及设置中断查询工作方式。【看一看就行,后面变成上手很快就会熟悉它】
● 样例:设 8259A 的两个端口地址为 20H 和 21H,OCW3、ISR、IRR 共用一个地址 20H。
读取 ISR 内容的程序段如下:
MOV AL, 00001011B
OUT 20H, AL ; 读 ISR 命令写入 OCW3
IN AL, 20H ; 读 ISR 内容至 AL
读取 IRR 内容的程序段如下:
MOV AL, 00001010B
OUT 20H, AL ; 读 IRR 命令写入 OCW3
IN AL, 20H ; 读 IRR 内容至 AL
● 尽管 8259A 只有两个端口地址,但不会混淆命令字和控制字,因为只有 ICW2、ICW3、ICW4和 OCW1 写入 8259A 的奇地址端口,且在初始化时,程序应严格按照系统规定的顺序写入,即先写入 ICW1,接着写 ICW2、ICW3、ICW4。【前面注重让对 奇地址 偶地址 进行记忆,原因就在这里,体现也在这里】
● 8259A 的初始化流程如下图所示:
● 样例:某微型计算机系统使用中、从两片 8259A 管理中断,从片中断请求INT
与主片的 IR2 连接。设主片工作于边沿触发、完全嵌套、非缓冲和非自动结束方式,中断类型号为 28H ~ 0FH
,端口地址为20H
和21H
。从片工作于边沿触发、完全嵌套、非缓冲和非自动结束方式,中断类型号为70H~77H
,端口地址0A0H
和0A1H
。试编写主片和从片的初始化程序。
主片 8259A 的初始化程序如下:
MOV AL, 00010001B ; 级联, 边沿触发, 需要写 ICW4
OUT 20H, AL ; 写 ICW1
MOV AL, 00001000B ; 预置主 8259A 中断类型码高 5 位为 0001
; 中断类型号为 08H
OUT 21H, AL ; 写 ICW2
MOV AL, 00000100B ; 主片的 IR2 引脚接从片
OUT 21H, AL ; 写 ICW3
MOV AL, 00000001B ; 完全嵌套、非缓冲、非自动结束方式
OUT 21H, AL ; 写 ICW4
从片 8259A 初始化程序如下:
MOV AL, 00010001B ; 级联, 边沿触发, 需要写 ICW~4~
OUT 0A0H, AL ; 写 ICW1
MOV AL, 01110000B ; 中断类型号为 70H
OUT 0A1H, AL ; 写 ICW2
MOV AL, 00000010B ; 主片的 IR2 引脚接从片
OUT 0A1H, AL ; 写 ICW3
MOV AL, 00000001B ; 完全嵌套、非缓冲、非自动结束方式
OUT 04AH, AL ; 写 ICW4
● 8259A 中断控制器是中断系统的核心器件,对系统 8259A 的初始化编程是在微机启动之后由 BIOS 自动完成的,设定的中断管理方式默认为:【后面编程一般也采用默认的中断管理方式】
① 系统 8259A 的中断触发方式为边沿触发,即上升沿为中断请求。
② 系统 8259A 的中断屏蔽方式采用常规屏蔽方式,即应用时,向 8259A 中断屏蔽寄存器写入适当屏蔽字即可 屏蔽/开放 某一级中断。
③ 中断源为固定优先级,即 IR0 中断请求级别最高,IR7 中断请求级别最低。
④ 采用常规中断结束方式,即在中断服务子程序结束之前向 8259A 送中断结束命令。
● 286 以上的微机,对 8259A 的编程分二步进行:
① 对 8259A 进行初始化编程(系统加电后,由 BIOS 完成)
② 对 8259A 进行应用编程(编写中断程序时完成,有2项内容:<1> 需要时,向 8259A 中断屏蔽寄存器写入屏蔽字。 <2> 每一个硬件中断服务程序结束前必须向 8259A 送中断命令字,通知 8259A 本次中断结束,否则 8259A 不能响应同一中断源的下次中断。注意:8259A 收到中断结束命令后,把 ISR 中的置1
位清0
!!)
● 非屏蔽(硬件)中断的定义:输入到NMI
引脚的中断请求信号而引发的中断。【在本文最开头让记忆的NMI
是否还有印象?】
● 响应非屏蔽中断的条件:
① NMI 引脚有(非屏蔽)中断请求,系统没有 DMA 请求。
② CPU 的当前指令执行完毕。
● CPU 响应非屏蔽中断过程:
① CPU 在每一条指令的最后一个时钟周期,检测 NMI 引脚。处理器不屏蔽来自 NMI 的中断请求。
② 处理器在响应 NMI 中断时,不从外部硬件接收中断向量号。在 80x86 中,非屏蔽中断所对应的中断向量号固定为2
。
③ 为了非屏蔽中断的嵌套,每当接受一个 NMI 中断,处理器就在内部屏蔽了再次响应的 NMI ,这一屏蔽过程直到执行中断返回指令IRET
后才结束。所以,NMI 处理程序应以IRET
指令结束。
● 可屏蔽(硬件)中断的定义:输入到 INTR 引脚的中断请求信号而引发的中断。【这个就是在本文最开头提到的INTR
】
● 硬件中断的级别: DMA 请求级别 > 非屏蔽中断 > 可屏蔽中断。
● 响应可屏蔽中断的条件:
① INTR引脚有可屏蔽中断请求,NMI引脚没有非屏蔽中断请求,系统没有 DMA 请求。
② CPU 对当前指令执行完毕。
③ CPU 处于开中断状态(即在标志寄存器中 I 标 = 1
)。
● CPU 响应可屏蔽中断过程:
① CPU 在每一条指令的最后一个时钟周期,检测 INTR 引脚。
② 当检测到有可屏蔽中断请求时,在满足上述条件的前提下,通过总线控制器向系统 8259A 发出中断响应信号(2
个负脉冲)。
③ CPU 在获得 8259A 送来的中断类型码之后,在实模式下查询中断向量表,从而转向相应中断源的中断服务程序。
● PC 系列机的可屏蔽中断硬件结构:
◆ 说明:
① 如上图所示,PC 系列机的可屏蔽中断使用的是两片 8259A 管理15
级中断。
② 各级硬件中断源及其中断类型码的分配如下表所示:
③ 系统默认分配给主 8259A 和从 8259A 的口地址如下表所示:【 为什么前面提到 “20H” 和 “21H” 这两个地址,原因在于此】
④ 硬件可屏蔽中断的中断级别:【由 “中断硬件结构图” 可知,主片 IR3 引脚接的从片的 INT】
⑤ 中断结束命令字 → 系统主、从 8259A 中断结束都采用常规结束方式,即在中断服务子程序结束之前向 8259A 发送常规中断结束命令20H
。另外,补充: ③ 系统默认分配给主 8259A 和从 8259A 的口地址如下表所示:【注意,下面代码中,第一个 20H 是个数(中断结束命令的标识数),第二个 20H 是个“地址”】
(1) 接入主 8259A 的 IR0, IR1, IR3 ~ IR7的中断源,其服务程序结束要向主 8259A 送中断结束命令字的程序段如下:
MOV AL, 20H
OUT 20H, AL
恢复现场
IRET
(2) 接入从 8259A 的中断源, 经主 8259A 的 IR2 向 INTR 提出中断请求, 其服务程序结束应分别向主、从 8259A 各送一个中断结束命令字 。
MOV AL, 20H
OUT 20H, AL
OUT 0A0H, AL
恢复现场
IRET
● 首先,什么是 “日时钟计数器” ?
答:BIOS 系统规定:40H:6CH ~ 40H:6FH
这4
个单元(共32
位)为日时钟计数器,每隔55ms
加1
次,一直计数到:001800B0H
,为24
小时,其计数值供系统软件使用。【40H:6CH ~ 40H:6FH
这个要多加记忆】
系统启动时, CPU 会执行 BIOS 中的一段程序,读取 CMOS 实时时钟电路的时间值 → 计数值 → 40:6CH ~ 40:6FH
作为日时钟计数器的计数初值。
● 系统日时钟的中断源是“系统 8254 0# 计数器”,每隔55ms
有一次中断请求。示意图如下:
● 系统日时钟的中断类型为:08H
(由上图可知,日时钟中断的请求信号接至系统主 8259A 的 IR0 ,然后查 5.3 的第二张表可知 08H 的由来)
● 系统日时钟的中断处理流程:
① 开启中断,保护现场(即 DS → 压栈)
② 然后40H
→ DS,对 “日时钟计数器” 加1
③ 测算软驱电动机的关闭时间
④ 执行INT 1CH
指令【 1CH 要留个印象】
⑤ 向主 8259A 发出常规中断结束命令(20H
)
⑥ 恢复现场,执行IRET
指令
● 关于1CH
服务程序的补充说明:该条命令即是8#
服务程序 ——> 每隔55ms
在DS = 40H
的前提下,调用一次1CH
服务程序,之后又返回08H 型
!!所以1CH
中断是日时钟的外扩中断,用户可开发新的1CH
中断(完成每55ms
一次的定时操作)取代原来的中断服务子程序。 (这一段我不太懂,做个标记⭐️)
① 置换中断向量:CPU 响应日时钟中断后,自动转向08H型
服务程序。根据 BIOS 设计的08H
型中断服务程序处理流程,可以知道,用户自行设计的定时中断服务程序类型可以是08H
,也可以是1CH
。
[1] 当用户程序的某项定时操作,其定时周期等于55ms
的整数倍时,可定义用户程序的定时操作为1CH
中断。此时需要置换08H
型中断向量,调用 DOS 系统25H
号子程序把用户定时中断服务程序入口地址写入4×1CH ~ 4×1CH+3
单元。【 25H 又出现了,上一次提到让着重记忆它是在 1.3 】
[2] 当用户程序的定时操作,其定时周期不等于55ms
55ms
的整数倍,或者小于55ms
时,定义用户中断服务程序为08H
型,此时需要置换08H
型中断向量,调用 DOS 系统25H
号子程序把用户定时中断服务程序入口地址写入4×08H ~ 4×08H+3
单元。
② 用户中断服务程序结束:【代码如下】
[1] 若用户定时中断定义为1CH
型,服务程序结束前,不需要向主 8259A 送中断结束命令。
[2] 若用户定时中断定义为08H
型,服务程序结束前,需要先向主 8259A 送中断结束命令。
MOV AL, 20H
OUT 20H, AL
③ 中断服务程序的执行时间:定时中断服务程序的执行时间,必须远远小于定时中断的时间间隔。
④ 避免 DOS 重入:中断是随机发生的。如果在执行某项中断服务子程序时,又执行类似INT 21H
的指令,则 CPU 又要 “重新进入” DOS,这一过程称为 “DOS 重入”,这是不允许的。
● 样例要求:利用 PC 系统机上的 8254 的 0 号定时计数器引发的日时钟中断,设计程序:每间隔 1 秒在 PC 终端屏幕上显示 1 行字符串 ‘HELLO!’,显示 10 行后结束。
● 设计思路:(可以用两种不同的方法实现该程序)
[1]
系统 8254 的0
号定时计数器每55ms
向系统主 8259A 的 I R 0 IR_0 IR0 端提1
次日时钟中断请求。
[2]
CPU 响应后转入08H
型中断服务程序,并在其中执行软件中断INT 1CH
(用该中断服务子程序实现输出功能)font>
[3]
用户可以利用这个55ms
执行一次的中断服务,设计程序段完成相应的功能。
● 方法一:
置换系统1CH
中断向量,将其指向自定义的中断服务程序。设定1
个计数变量,每当系统提请18
次日时钟中断时,在自定义的中断服务程序中完成1
次字符串显示。为此,需要进行的操作为:
[1]
保存原来系统的1CH
中断向量到数据段OLD1C
双字单元。(为什么要取这个怪调调的变量名OLD1C
,希望评论指点)
[2]
置换1CH
中断向量使其指向我们自己的中断服务程序。
[3]
中断服务程序每执行18
次时,在其中显示1
次字符串(注:18x55ms=990ms 大约为 1s)。【为什么前面要设置 18 次的原因 】
[4]
在返回操作系统前恢复原来保存的1CH
中断向量。
[5]
程序框图如下图所示。
● 代码如下:【 25H、35H 再次出现了(只不过它们和1CH组合出现了而已),他俩最原始的定义在 1.3 】
.486
;---------------------------------
DATA SEGMENT USE16
MESG DB 'HELLO!',0DH,0AH,'$'
OLD1C DD ?
ICOUNT DB 18 ; 中断计数初值
COUNT DB 10 ; 显示行数控制
DATA ENDS
;---------------------------------
CODE SEGMENT USE16
ASSUME CS:CODE,DS:DATA
BEG:
MOV AX,DATA
MOV DS,AX
CLI ; 关中断
CALL READ1C
CALL WRITE1C
STI ; 开中断
SCAN:
CMP COUNT,0
JNZ SCAN ; 是否已经显示 10 行,否则转
CALL RESET
MOV AH,4CH
INT 21H
;---------------------------------
SERVICE PROC
PUSHA ; 保护现场
PUSH DS ; DS = 40H
MOV AX,DATA
MOV DS,AX ; 重新给 DS 赋值
DEC ICOUNT ; 中断计数
JNZ EXIT ; 不满 18 次转
MOV ICOUNT,18
DEC COUNT ; 显示行数减1
MOV AH,9 ; 显示字符串
LEA DX,MESG
INT 21H
EXIT:
POP DS ; 恢复现场
POPA
IRET ; 返回系统 8 型中断服务程序
SERVICE ENDP
;----------------------------------
READ1C PROC ; 转移系统 1CH 型中断向量
MOV AX,351CH
INT 21H
MOV WORD PTR OLD1C,BX
MOV WORD PTR OLD1C+2,ES
RET
READ1C ENDP
;---------------------------------
WRITE1C PROC ; 写入用户 1CH 型中断向量
PUSH DS
MOV AX,CODE
MOV DS,AX
MOV DX,OFFSET SERVICE
MOV AX,251CH
INT 21H
POP DS
RET
WRITE1C ENDP
;---------------------------------
RESET PROC ; 恢复系统 08 中断向量
MOV DX,WORD PTR OLD1C ; 注意和后一条指令的顺序(不能交换)
MOV DS,WORD PTR OLD1C+2
MOV AX,2508H
INT 21H
RET
RESET ENDP
;---------------------------------
CODE ENDS
END BEG
● 运行结果如下:
● 程序分析:
① 方法一程序的执行过程如下图所示:【其实对下面这张图里的 20H 我不太清楚怎么来的,毕竟代码里面没有,后面可能期末复习时会有补充 】② 在进入用户定义的中断服务程序后,需要保存 DS 并重新对 DS 进行赋值。在中断返回前,需要恢复 DS。
③RESET
子程序代码如下:【注:两条指令先后顺序不可颠倒。】MOV DX, WORD PTR OLD1C MOV DS, WORD PTR OLD1C+2
④ 用户定义的中断服务程序中不需要对系统主 8259A 写中断结束命令字。
⑤ 在本程序的中断服务程序中使用了 DOS 功能调用来显示字符串。这是一种不推荐的做法。在程序设计考虑不周到时容易发生 DOS 重入问题。因此,我们应该尽量避免在中断服务程序中使用 DOS 功能调用,而用 BIOS 功能调用替换之。
● 方法二:置换系统08H
型中断向量,将其指向自定义的中断服务程序。设定1
个计数变量,每当系统提请18
次日,时钟中断时在自定义的中断服务程序中完成1
次字符串显示。
步骤如下:
① 保存原来系统的08H
中断向量到代码段OLD08
双字单元。CODE SEGMENT USE16 OLD08 DD ? ; 保存系统 08H 中断向量的变量 ASSUME CS:CODE,DS:DATA
② 置换
08H
中断向量使其指向我们自己的中断服务程序
③ 在每次中断服务程序的末尾调用1
次日时钟中断服务程序JMP CS:OLD08
④ 原来系统
08H
中断需要完成的任务,包括往主 8259A 写中断结束命令字,返回断点等 均在原来的中断服务程序中完成。SERVICE PROC ; 中断服务程序 PUSHA PUSH DS MOV AX,DATA MOV DS,AX DEC ICOUNT ; 计 18 次, 55ms × 18 = 990ms ≈ 1s JNZ EXIT MOV ICOUNT,18 DEC COUNT ; 显示行数减 1 MOV AH,9 ; 显示字符串 MOV DX,OFFSET MESG INT 21H EXIT: POP DS POPA JMP CS:OLD08 ; 转向原来的 08H 服务程序 SERVICE ENDP
⑤ 中断服务程序每执行
18
次时在其中显示1
次字符串(18 x 55ms = 990ms)大约为1s
.
⑥ 在返回操作系统前恢复原来保存的08H
中断向量。
⑦ 程序框图如图下所示:
● 代码如下:【 25H、35H 再次出现了(只不过它们和08H组合出现了而已),他俩最原始的定义在 1.3 】
.486
;----------------------------------------
DATA SEGMENT USE16
MESG DB 'HELLO!',0DH,0AH,'$'
ICOUNT DB 18
COUNT DB 10
DATA ENDS
;----------------------------------------
CODE SEGMENT USE16
OLD08 DD ? ; 代码段中保存系统 08H 中断向量的变量
ASSUME CS:CODE,DS:DATA
BEG:
MOV AX,DATA
MOV DS,AX
CLI ; 关中断
CALL READ08 ; 保存原来的 08 中断向量
CALL WRITE08 ; 置换 08H 型中断向量指向自定义中断服务程序
STI ; 开中断
SCAN:
CMP COUNT,0
JNZ SCAN ; 是否已经显示 10 行,否转
CLI
CALL RESET ; 恢复系统 08 中断向量
STI
MOV AH,4CH
INT 21H ; 返回 DOS
;----------------------------------------
SERVICE PROC ; 中断服务程序
PUSHA
PUSH DS
MOV AX,DATA
MOV DS,AX
DEC ICOUNT ; 计 18 次, 55ms × 18 = 990ms ≈ 1s
JNZ EXIT
MOV ICOUNT,18
DEC COUNT ; 显示行数减 1
MOV AH,9 ; 显示字符串
MOV DX,OFFSET MESG
INT 21H
EXIT:
POP DS
POPA
JMP CS:OLD08 ; 转向原来的 08H 服务程序
SERVICE ENDP
;----------------------------------------
READ08 PROC ; 保存原来系统的 08H 中断向量
MOV AX,3508H
INT 21H
MOV WORD PTR OLD08,BX
MOV WORD PTR OLD08+2,ES
RET
READ08 ENDP
;----------------------------------------
WRITE08 PROC ; 置换 08H 型中断向量指向自定义中断服务程序
PUSH DS
MOV AX,CODE
MOV DS,AX
MOV DX,OFFSET SERVICE
MOV AX,2508H
INT 21H
POP DS
RET
WRITE08 ENDP
;----------------------------------------
RESET PROC ; 恢复系统 08 中断向量
MOV DX,WORD PTR OLD08 ; 注意和后一条指令的顺序
MOV DS,WORD PTR OLD08+2
MOV AX,2508H
INT 21H
RET
RESET ENDP
;----------------------------------------
CODE ENDS
END BEG
● 程序分析:
① 方法二程序的执行过程如图所示。【其实对里面的 20H 我也不太清楚怎么来的,可能后面期末复习时会有补充 】
② 在进入用户定义的中断服务程序后,需要保存 DS 并重新对 DS 进行赋值。在中断返回前,需要恢复 DS 。注意
1CH
中断和08H
中断两个服务程序其使用的原因和保存的内容不同。
③ RESET 子程序中两条指令先后顺序不可颠倒。MOV DX,WORD PTR OLD1C MOV DS, WORD PTR OLD1C+2
④
OLD08
双字单元必须定义在代码段,不能设置在数据段。这样做能保证每次中断服务程序的末尾,能顺利地转到系统日时钟中断服务程序。
⑤ 本例中用户定义的中断服务程序中不需要对系统主 8259A 写中断结束命令字,因为在用户定义的中断服务程序的最后,由指令JMP CS:OLD08
将程序转移到系统日时钟中断服务程序 。在系统日时钟中断服务程序返回之前,向主 8259A 写了中断结束字。
● 运行结果:和方法一的结果一样。
● 键盘中断源:主板键盘接口电路。系统键盘中断请求示意图如下:【IR1 留个印象】
● 中断类型:09H
,键盘中断请求的请求信号接至主 8259A 的 IR1。【09H 多加记忆 】
● 微型计算机键盘的构成:主要由单片机、译码器和键开关矩阵三大部分组成,通过一根5
芯电缆与主板键盘接口电路相连。
● 微型计算机键盘的使用原理:键盘以矩阵格式进行排列,对按下的键的识别(它的行、列位置的扫描码)的产生是由键盘内部的单片机通过译码器来实现的。(大白话说明:键盘电路以单片机为核心,加电后固化在单片机内部的键盘扫描程序,不断扫描每一个按健,一旦有键闭合,就把闭合键的扫描码,即位置码 → 键盘接口电路)
● BIOS 设计的09H
型中断服务程序处理流程如下:
① 开中断、保护现场。
② 从键盘接口电路(口地址60H
)读取按键扫描码。
③ 分析、处理安检扫描码,生成相应的键代码存入键盘缓冲区。
④ 向 主8259A 发常规中断结束命令
MOV AL,20H
OUT 20H,AL
⑤ 恢复现场,执行IRET
命令。
① 开发应用一:键盘缓冲区
● 系统 BIOS 规定:系统 RAM 中 40:1EH ~ 40:3DH
为键盘缓冲区共32
个单元。但实际使用30
个单元,存放15
个键的键代码。键盘缓冲区是以 “先进先出” 的规则存取。
● 由9
型服务程序写入键代码,用户用INT 16H
访问键盘缓冲区,所以键盘缓冲区是9
型硬中断和INT 16H
软中断之间交换信息的缓冲区。
② 开发应用二:键盘状态字节
系统 RAM 中40:17H
单元为键盘状态单元,用来记录控制键和切换键的状态。
③ 开发应用三:读取键盘缓冲区【有以下两种方式可以读取键盘缓冲区中的内容】
[1] 直接从60H
端口中读取键盘扫描码,在应用程序中分析键盘输入的是字符还是控制符、切换符等。
[2] 利用 BIOS 提供的中断INT 16H
。
● 中断源:(系统实时时钟的中断源是)主板上的实时时钟电路。其中断的请求途径如下图所示:
● 实时时钟中断源包括:周期中断和报警中断。这两种中断中的任何一个中断请求都将引发实时时钟中断。
① 报警中断在 “允许周期中断” 的前提下,每隔976.562μs
(即1/1024KHZ
),产生一次周期中断请求。其中1024KHZ
是由基准频率32.768HZ
经过分频(分频系数由初始化编程确定)得到。
② 在 “允许报警中断” 的前提下,当实时时钟达到预置的报警时间时,产生一次报警中断请求。
● 中断类型:70H
。(由上图可知,实时时钟中断的请求信号接至系统从 8259A 的 IR0 ,由从 8259A 的INT
端接至主 8259A 的 IR2 ,最后由主 8259A 的INT
端向 CPU 的INTR
引脚提出可屏蔽硬件请求)【70H 的来由,可见 5.3 的第二张表】
① 开中断,保护现场;
② 读取状态寄存器,判断是否是周期中断?若是,则…(进行相关操作)。若不是则进入下一步。
③ 判断是否是报警中断。若是,则执行INT 4AH
,转入报警中断处理程序。报警中断处理程序结束,执行IRET
返回下一步。若不是报警中断,则直接进入下一步。
④ 向主 8259A 发常规中断结束命令。
MOV AL, 20H
OUT 20H, AL
OUT 0A0H, AL
⑤ 恢复现场,执行IRET
命令。
① 预制周期中断等待时间 —— INT 15H
的83H
号子功能
入口参数:
[1] 置 AL=0,表明是预置等待时间;
[2] 置 CX、DX=等待时间的微秒数,其中 CX 为高16
位二进数,DX 为低16
位二进数。
[3] 置 ES:BX=用户等待标志的逻辑地址。
出口参数:
C 标志置1
,表示预置失败。C标志置0
,表示预置成功。
② 复位报警,为预置报警时间做准备 —— INT 1AH
的07H
号子功能
入口参数: 无。
出口参数: 无。
③ 预置报警时间 —— INT 1AH
的06H
号子功能
入口参数:
[1] 置 CH=报警时刻的小时数 (0~23
的BCD码数)。
[2] 置 CL=报警时刻的分钟数(0~59
的BCD码数)。
[3] 置 DH=报警时刻的秒数 (0~59
的BCD码数)。
出口参数:
C 标志置1
,表示预置失败。C 标志置0
,表示预置成功。
● 中断源:(系统用户中断的中断源是)系统的 ISA 总线 B4 端子(IRQ9)引入的中断请求信号。且用户中断请求示意图如下图所示:[ISA 的知识点在第【计算机原理与接口技术(UNIX)⑬】——总线概述【总线与总线标准、总线结构、ISA、PCI、IDE】中】
● 中断类型:71H
(由上图可知,用户中断的请求信号接至系统的 从8259A 的 IR1 ,由 从8259A 的INT
端接至 主8259A 的 IR2 ,最后由 主8259A 的INT
端向 CPU 中的INTR
引脚提出可屏蔽硬件请求。由 5.3 的第二张表可知 71H 的由来)
● BIOS 设计的71H
型中断服务程序处理流程如下:
① 开中断、保护现场;
② 向 从8259A 发出中断结束命令
MOV AL, 20H
OUT 0A0H, AL
③ 执行INT 0AH
,转向0AH
服务程序。(0AH
服务程序是用户预先设计好的,其中断向量已经存放在系统 RAM 中的4×0AH~4×0AH+3
单元。)
● 用户中断是微机系统为用户开发可屏蔽中断预备的中断口。在用户中断程序的设计中,需要采取以下措施:
① 把外扩中断源的中断请求(由低电平到高电平的跃变)接入 ISA 总线 B4 端子。
② 开放用户中断。
● 用户中断请求的途径:如上图所示,用户中断请求从 ISA 总线 B4 端子(IRQ9)引入,依次经过 主8259、从8259 二级中断管理,最后由 主8259A 向 CPU 提出中断请求。
● 只有 从8259A 的 IMR1 置
0
,主8259A 的 IMR2 置0
,其中断请求方能送到 CPU。● 实现用户中断必须对 主、从8259A 的应用编程,保证中断申请由 8259中断控制器 提向 CPU。代码如下:
IN AL, 0A1H AND AL, 11111101B OUT 0A1H, AL ; 开放用户中断 IN AL, 21H AND AL, 11111011B OUT 21H, AL ; 开放 从8259A 中断
③ 置换中断向量:CPU 响应用户中断后,自动转向71H
型服务程序。根据 BIOS 设计的71H
型中断服务程序处理流程,可以知道,用户自行设计的用户中断服务程序类型可以是71H
,也可以是0AH
。
[1] 若定义用户中断服务程序为0AH
型,则置换0AH
型中断向量,调用 DOS 系统25H
号子程序把用户中断的服务程序入口地址写入4×0AH~4×0AH+3
单元。
[2] 若定义用户中断服务程序为71H
型,则置换71H
型中断向量,调用 DOS 系统25H
号子程序把用户中断的服务程序入口地址写入4×71H ~ 4×71H+3
单元。
④ 用户中断服务程序结束时,向 8259A 写结束字。
[1] 若用户中断定义为0AH
型,服务程序结束前只向 主8259A 送结束命令。
MOV AL, 20H
OUT 20H, AL
[2] 若用户中断定义为71H
型, 服务程序结束前,向 主、从8259A 各送一中断结束命令 。
MOV AL, 20H
OUT 20H, AL
OUT 0A0H, AL
● 题目要求:一外扩 8254 0# 计数器输出是周期为 100ms 的方波,将该 8254 的 OUT0 接至系统总线插槽 B4 端子,如下图所示。利用该 8254 的 OUT0 输出作为定时中断源,编程实现每隔 1 秒在屏幕上显示字符串 ‘HELLO!’,主机有按键时显示结束。
● 设计思路:该中断请求是经 B4 端子接入的,CPU 响应后转入71H
型中断服务程序,并在其中执行软件中断INT 0AH
。所以,可以定义用户服务程序的类型为0AH
。并且设定1
个计数变量,每当 B4 端子接收到第10
次用户中断,在自定义的中断服务程序中完成1
次字符串显示。为此,需要进行的操作为:
① 保存原来系统0AH
中断向量到数据段OLD1C
双字单元
② 置换0AH
中断向量使其指向用户自行设计的中断服务程序
③ 打开用户中断
④ 中断服务程序每执行10
次时在其中显示1次字符串( 10x100ms = 1s)
⑤ 服务程序结束前向 主8259A 送结束命令;
⑥ 在返回操作系统前恢复原来保存的0AH
中断向量。
⑦ 程序框图图如下图所示:
● 代码如下:【我调试了很久的下面代码,还是没有结果,后面问老师进行修改】
.486
;---------------------------------
DATA SEGMENT USE16
MESG DB 'HELLO!',0DH,0AH,'$'
OLD0A DD ?
ICOUNT DB 10 ; 中断计数初值
DATA ENDS
;---------------------------------
CODE SEGMENT USE16
ASSUME CS:CODE,DS:DATA
BEG:
MOV AX,DATA
MOV DS,AX
CLI ; 关中断
CALL READ0A
CALL WRITE0A
CALL I8259A
STI ; 开中断
SCAN:
MOV AH,1
INT 16H ; 是否有键入
JZ SCAN ; 无键入,转
CLI
CALL RESET
STI
MOV AH,4CH
INT 21H
;---------------------------------
SERVICE PROC
PUSHA ; 保护现场
PUSH DS ; DS = 40H
MOV AX,DATA
MOV DS,AX ; 重新给 DS 赋值
DEC ICOUNT ; 中断计数
JNZ EXIT ; 不满 10 次转
MOV ICOUNT,10
MOV AH,9 ; 显示字符串
;MOV DX,OFFSET MESG
LEA DX,MESG
INT 21H
EXIT:
MOV AL,20H
OUT 20H,AL ; 给主8259A写结束字
POP DS ; 恢复现场
POPA
IRET ; 返回系统 71 型中断服务程序
SERVICE ENDP
;----------------------------------
READ0A PROC ; 转移系统 0AH 型中断向量
MOV AX,350AH
INT 21H
MOV WORD PTR OLD0A,BX
MOV WORD PTR OLD0A+2,ES
RET
READ0A ENDP
;---------------------------------
WRITE0A PROC ; 写入用户 0AH 型中断向量
PUSH DS
MOV AX,CODE
MOV DS,AX
MOV DX,OFFSET SERVICE
MOV AX,250AH
INT 21H
POP DS
RET
WRITE0A ENDP
;---------------------------------
I8259A PROC
IN AL,0A1H
AND AL,11111101B
OUT 0A1H,AL ; 从8259A 的 IMR1 置 0
IN AL,21H
AND AL,11111011B
OUT 21H,AL ; 主8259A 的 IMR2 置 0
RET
I8259A ENDP
;---------------------------------
RESET PROC ; 恢复系统 0AH 型中断向量
MOV DX,WORD PTR OLD0A
MOV DS,WORD PTR OLD0A+2
MOV AX,250AH
INT 21H
RET
RESET ENDP
;---------------------------------
CODE ENDS
END BEG
● 程序分析:
① 程序的执行过程如下图所示:
② 在进入用户定义的中断服务程序后,需要保存 DS 并重新对 DS 进行赋值。在中断返回前,需要恢复 DS 。
③ RESET 子程序中,两条指令先后顺序不可颠倒。MOV DX, WORD PTR OLD0A MOV DS, WORD PTR OLD0A+2
④ 用户定义的中断服务程序中需要对系统 主8259A 写中断结束命令字。
● 运行结果:…【我调试了很久的上面代码,还是没有结果,后面请教下老师】
● 硬件中断和软件中断的相同点:
① 都会引起程序中止。
② CPU 获得中断类型码n
后,自动从4×n ~ 4×n+3
单元取出该中断源的中断向量 → IP、CS,从而执行该中断源的中断服务程序。
● 硬件中断和软件中断的区别 :
① 中断的引发方式不同
② CPU 获取中断类型码的方式不同
③ CPU 响应的条件不同
④ 中断处理程序的结束方式不同
① 中断基本概念(中断、中断源、中断系统及其功能、中断指令、中断向量、中断向量表及其作用)
② PC系统中断分类(CPU中断、软件中断及响应过程、硬件中断——>[可屏蔽与非屏蔽中断的概念与区别,响应条件])
③ 系统响应可屏蔽中断的过程
④ PC/AT系统的可屏蔽中断结构(几个重要的中断源、中断类型码和中断响应过程)
⑤ 中断程序的设计
[1]《微型计算机原理与接口技术(慕课板)》
清华大学出版社
[2] 中断类型表
链接:https://www.cnblogs.com/haiming/archive/2012/10/20/2731892.html.
[3] INT 21H 指令说明及使用方法
链接:https://study-life.blog.csdn.net/article/details/79926484.
上一篇文章链接:【计算机原理与接口技术(UNIX)⑮】——输入/输出系统【查询方式、中断控制方式、DMA 、8237A】.
下一篇文章链接:【计算机原理与接口技术(UNIX)⑰】——微型计算机系统的串行通信 [ 8250 + 具体样例 + 上机实验].
不知鼠标滚轮翻了多少转,才滑到了底… ⭐️ ⭐️