1、利用系统总线上中断请求信号MIR7 ,设计一个单一中断请求实验。
2、利用系统总线上中断请求信号MIR6和MIR7,设计一个双中断优先级应用实验,观察8259对中 断优先级的控制。
3、利用系统总线上中断请求信号MIR7和SIR1,设计一个级连中断应用实验。
中断控制器8259简介
在Intel 386EX芯片中集成有中断控制单元,该单元包含有两个级联中断控制器,一个为主控制器,一个为从控制器。该中断控制单元就功能而言与工业上标准的82C59A是一致的,操作方法也相同。从片的INT连接到主片的IR2信号上构成两片8259的级联。本实验中,将主控制器的IR6、IR7以及从控制器的IR1开放出来供实验使用,主片8259的IR4供系统串口使用。8259的内部连接及外部管脚引出如下图:
在总线控制器控制下,8259A芯片可以处于编程状态和操作状态。编程状态通过CPU的IN或OUT指令对8259A芯片进行初始化编程。完成初始化编程后,芯片即可进入操作状态,此时芯片即可随时响应外部设备提出的中断请求(IRQ0 -IRQ15),同时系统还可以使用操作命令字随时修改其中断处理方式。通过中断判优选择,芯片将选中当前最高优先级的中断请求作为中断服务对象,并通过CPU引脚INT通知CPU中断请求的到来,CPU响应后,芯片从数据总线D7-D0将编程设定的当前服务对象的中断号送出,CPU由此获取对应的中断向量值,并执行中断服务程序。逻辑图如下:
(图有亿点点丑,别介意,只要能看清就ok)
下面列出本实验会用到的中断控制单元寄存器列表(它们都是8位的)
寄存器 | 口地址 | 功能描述 |
ICW1(主) ICW1(从) (只写) |
0020H 00A0H |
初始化命令字1 决定中断请求信号为电平触发还是边沿触发。 |
ICW2(主) ICW2(从) (只写) |
0021H 00A1H |
初始化命令字2 包含了8259的基址中断向量号,基址中断向量是IRO的向量号,基址加1就是 IR1的向量号,依此类推。 |
ICW3(主) (只写) |
0021H |
初始化命令字3: 用于识别从8259设备连接到主控制器的IR信号,内部的从8259连接到主8259 的IR2信号上。 |
ICW3(从) (只写) |
00A1H | 初始化命令字3 表明内部从控制器级联到主片的IR2信号上。 |
ICW4(主) ICW4(从) (只写) |
0021H 00A1H |
初始化命令字4 选择特殊全嵌套或全嵌套模式,使能中断自动结束方式。 |
OCW1(主) OCW1(从) (只写) |
0021H 00A1H |
操作命令字1 中断屏蔽操作寄存器,可屏蔽相应的中断信号。 |
OCW2(主) OCW2(从) (只写) |
0020H 00A0H |
操作命令字2 改变中断优先级和发送中断结束命令。 |
想问下,一路看下来的你,头大没有qwq
其实不用挨着看完,看完然后,就会忘了前面是啥。我们用到哪个寄存器就去查看它的作用。
到这里,或许你会问,这些寄存器咋个赋值,如何才能使用中断,我们下面继续。
在8259A工作之前,首先设置初始化命令字 ICW 寄存器组。而工作中,可以使用写入操作命令字 OCW 寄存器组来随时设置和管理8259A的工作方式。
1、ICW1设置(对于本实验,都设置为11H,即0001 0001)
2、ICW2设置
这里先需要一张中断矢量地址与中断号的对应表
主片中断序号 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
矢量地址 | 20H - 23H | 24H - 27H | 28H - 2BH | 2CH - 2FH | 30H - 33H | 34H - 37H | 38H - 3BH | 3CH -3FH |
从片中断序号 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
矢量地址 | C0H - C3H | C4H - C7H | C8H - CBH | CCH - CFH | D0H - D3H | D4H - D7H | D8H - DBH | DCH - DFH |
此处引出一个公式:中断向量地址 = 中断向量类型号*4。这个中断向量类型号就是要设置的ICW2,但不完全是。下图是ICW2的格式,后三位一般设置为0,会由8259自动按照IRQ0-IRQ7填入。
好了,那么该如何设置ICW2捏,那么根据上面的红色公式和矢量地址与中断号表格,先算出中断向量号类型码,即中断向量地址除以4,即右移两位,然后把后三位置0就好了。
3、ICW3设置
下图是主片的ICW3设置(本实验设置为0000 0100)
下图是从片的ICW3设置(本实验这样设置)
4、ICW4设置(下图是ICW4格式,本实验直接设置为0000 0001)
5、OCW1设置
OCW18位,为1则表示相应的位对应的IRi中断被屏蔽,为0则不屏蔽。
6、ICW2设置(本实验设置为0010 0000)
终于介绍完相关寄存器的配置了,下面上代码,qwq
第一个小实验,外部会给主片的IR7脉冲信号,产生中断,由于各个学校实验不同,本实验是按下按键,给主片的IR7一个脉冲,然后产生中断,显示字符“7”。代码步骤,先把服务中断程序的入口地址填入中断矢量表,然后配置8259A的相关寄存器,最后编写显示字符7的程序。
SSTACK SEGMENT STACK
DW 32 DUP(?)
SSTACK ENDS
CODE SEGMENT
ASSUME CS:CODE
START: PUSH DS
MOV AX, 0000H
MOV DS, AX
MOV AX, OFFSET MIR7 ; 取中断程序入口地址
MOV SI, 003CH ; 中断矢量地址
MOV [SI], AX ; 填IRQ7的偏移矢量
MOV AX, CS ; 段地址
MOV SI, 003EH
MOV [SI], AX ; 填IRQ7的段地址矢量
CLI ; 配置好相关寄存器之前,先禁止中断发生
POP DS
; 上面这段,是往中断向量表填入中断服务程序的入口地址,先取我们自己编写的中断服务程序的偏
; 移地址,填到AX,然后再把AX里的值写入DS:SI对应地址里,因为第1个实验利用MIR7,所以查表
; 对应主片中断序号7所对应的矢量地址为3CH-3FH。这里写了两次,一次往3CH,一次往3EH,下面
; 会详细介绍,为什么这样写。
; 初始化主片8259相关寄存器
MOV AL, 11H
OUT 20H, AL ; ICW1,边沿触发
MOV AL, 08H
OUT 21H, AL ; ICW2,低三位根据设置的IR自动填入 0000 1000
MOV AL, 04H
OUT 21H, AL ; ICW3,从芯片连接到主芯片的IR2信号上
MOV AL, 01H
OUT 21H, AL ; ICW4
MOV AL, 6FH ; OCW 10110 1111 开放4号中断串口用,7号中断实验用
OUT 21H, AL
STI ; 允许中断发生
AA1: NOP
JMP AA1 ; 等待中断信号
MIR7: STI
CALL DELAY ; 延时
MOV AX, 0137H
INT 10H ; 显示字符7,ASCII为56 = 7 + 3*16 ->al
MOV AX, 0120H ; 空格,ASCII为32 = 16*2
INT 10H ; 调用8086系统10号中断显示字符,把AL的值对应的ASCII显示出来
MOV AL, 20H
OUT 20H, AL ; OCW2,发送中断结束命令
IRET ; iret interrupt return中断返回指令
DELAY: PUSH CX
MOV CX, 0F00H
AA0: PUSH AX
POP AX
LOOP AA0 ; 循环0F00H次,相当于延时
POP CX
RET ; 函数返回
CODE ENDS
END START
小实验1的代码给出来了,下面对一些问题做解释。先给一些概念作解释。
中断向量:即中断服务子程序的入口逻辑地址,由两部分组成:服务程序的段基址CS(2字节)和服务程序的偏移地址IP(2字节)。
中断向量表:存放中断向量的一个特定的内存区域,位于整个内存区域的最低端,物理地址范围从00000H~003FFH(一个中断向量占4字节的空间,因此256个中断一共需要1K字节的空间)。共256个中断,中断类型号从0~255。
中断向量地址 = 中断类型号*4(即可找到中断向量地址,前两位送给偏移量后两位送给段基址)
把服务中断程序的入口地址填入中断矢量表这里,为什么填两次。首先,8086是16位的,那么寄存器就是16位的,包括CS和IP,机器执行程序时,会把段地址给CS,偏移地址给IP,所以,想要让机器停下来它正在做的事,执行我们写好的中断服务程序,就必须把中断服务程序的段地址和偏移地址放到一个地方(中断矢量表),机器会自动去取,所以要填两次,而且是填偶地址。如下图。
对于显示程序就简单了,调用系统自带的10号中断,提前把字符7的ASCII码填入AL就可以了。
第二个小实验,外部会给主片的IR6、主片的IR7脉冲信号,产生中断,由于各个学校实验不同,本实验是按下按键,给主片的IR6或主片的IR7一个脉冲,然后产生中断,显示字符“6”或“7”。代码步骤,和第一个小实验相同,只是配置中断矢量表多了一个,其余就是OCW2发生相应的变化。直接给出代码。
SSTACK SEGMENT STACK
DW 32 DUP(?)
SSTACK ENDS
CODE SEGMENT
ASSUME CS:CODE
START: PUSH DS
MOV AX, 0000H
MOV DS, AX
MOV AX, OFFSET MIR7 ; 取中断服务程序显示字符7的入口地址
MOV SI, 003CH
MOV [SI], AX ; 填IRQ7的偏移矢量
MOV AX, CS ; 段地址
MOV SI, 003EH
MOV [SI], AX ; 填IRQ7的段地址矢量
MOV AX, OFFSET MIR6 ; 取中断服务程序显示字符6的入口地址
MOV SI, 0038H
MOV [SI], AX ; 填IRQ6的偏移矢量
MOV AX, CS
MOV SI, 003AH
MOV [SI], AX
CLI
POP DS
;初始化主片8259
MOV AL, 11H
OUT 20H, AL ; ICW1,边沿触发
MOV AL, 08H
OUT 21H, AL ; ICW2
MOV AL, 04H
OUT 21H, AL ; ICW3,从芯片连接到主芯片的IR2信号上
MOV AL, 01H
OUT 21H, AL ; ICW4
MOV AL, 2FH
OUT 21H, AL ; OCW1 0010 1111 开放4号中断串口用,6、7号中断实验用
STI ; 允许中断发生
AA1: NOP
JMP AA1 ; 一直等待中断信号
MIR7: STI ; 允许中断发生
CALL DELAY
MOV AX, 0137H
INT 10H ; 显示字符7
MOV AX, 0120H
INT 10H
MOV AL, 20H
OUT 20H, AL ; 中断结束命令
IRET ; iret interrupt return中断返回指令
MIR6: STI ; 允许中断发生
CALL DELAY
MOV AX, 0136H
INT 10H ; 显示字符6
MOV AX, 0120H
INT 10H
MOV AL, 20H
OUT 20H, AL
IRET ; iret interrupt return中断返回指令
DELAY: PUSH CX
MOV CX, 0F000H
AA0: PUSH AX
POP AX
LOOP AA0 ; 循环0F00H次,延时
POP CX
RET ; 函数返回
CODE ENDS
END START
第三个小实验,外部会给从片的IR6、主片的IR7脉冲信号,且产生中断,从片连接到主片的IR2上。由于各个学校实验不同,本实验是按下按键,给IR6或IR7一个脉冲,然后产生中断,显示字符“S1”或“M7”。代码步骤,和第二个小实验相同,只是配置中断矢量表多了一个,其余就是OCW2发生相应的变化。直接给出代码。
SSTACK SEGMENT STACK
DW 32 DUP(?)
SSTACK ENDS
CODE SEGMENT
ASSUME CS:CODE
START: PUSH DS
MOV AX, 0000H
MOV DS, AX
MOV AX, OFFSET MIR7 ; 取中断入口地址
MOV SI, 003CH ; 中断矢量地址
MOV [SI], AX ; 填IRQ7的偏移矢量
MOV AX, CS ; 段地址
MOV SI, 003EH
MOV [SI], AX ; 填IRQ7的段地址矢量
MOV AX, OFFSET SIR1
MOV SI, 00C4H
MOV [SI], AX ; 从芯片偏移地址送入中断矢量地址
MOV AX, CS
MOV SI, 00C6H
MOV [SI], AX ; 从芯片的基地址
CLI
POP DS
;初始化主片8259
MOV AL, 11H
OUT 20H, AL ; ICW1
MOV AL, 08H ; ICW2,低三位根据设置的IR自动填入
OUT 21H, AL ; ICW2
MOV AL, 04H
OUT 21H, AL ; ICW3,从芯片连接到主芯片的IR2信号上
MOV AL, 01H
OUT 21H, AL ; ICW4,设置嵌套方式为默认
;初始化从片8259
MOV AL, 11H
OUT 0A0H, AL ; ICW1,边沿触发
MOV AL, 30H
OUT 0A1H, AL ; ICW2,低三位根据设置的IR自动填入 矢量地址=类型码*4
MOV AL, 02H
OUT 0A1H, AL ; ICW3,从芯片选择的是IR1,即0010
MOV AL, 01H
OUT 0A1H, AL ; ICW4,设置嵌套方式为默认
MOV AL, 0FDH
OUT 0A1H,AL ; OCW1 = 1111 1101 ,从芯片的1号不屏蔽,其余屏蔽
MOV AL, 6BH
OUT 21H, AL ; 主8259 OCW1 01101011 IR2、IR7不屏蔽,IR4用于串口
STI ; 允许中断发生
AA1: NOP
JMP AA1
MIR7: STI
CALL DELAY
MOV AX, 014DH
INT 10H ; 显示字符M
MOV AX, 0137H
INT 10H ; 显示字符7
MOV AX, 0120H
INT 10H ; 空格
MOV AL, 20H
OUT 20H, AL ; OCW2,中断结束命令
IRET
SIR1: STI
CALL DELAY
MOV AX, 0153H
INT 10H ; 显示字符S
MOV AX, 0131H
INT 10H ; 显示字符1
MOV AX, 0120H
INT 10H ; 空格
MOV AL, 20H
OUT 0A0H, AL
OUT 20H, AL ; OCW2, 中断结束命令
IRET
DELAY: PUSH CX
MOV CX, 0F00H
AA0: PUSH AX
POP AX
LOOP AA0
POP CX
RET
CODE ENDS
END START
最后,附上我学习中遇到的问题,不知道看完的你有没有这样的困惑。就是在对8259A进行编程时,如何识别4条ICW命令和3条0CW命令。
(1)首先看命令是被送入奇地址端口还是偶地址端口,若被送入偶地址端口可能是命令
字ICW、0CW或0CW2;若被送入奇地址端口可能是命令字ICW2、 ICWs、 ICW.或 OCW.。
(2)当端口地址为偶地址时,命令字ICW.、0CW2、 0CW 的区分方法如下:
A、当命令字的D4=1时,为ICW1
B、当命令字的D4D3=00时,为0CW2
C、当命令字的D4D3=01时,为0CWs
(3)当端口地址为奇地址时,命令字ICW2、 ICW3、 ICW4、0CW1的区分方法如下:
A、若前一个命令字为ICW1, 则该命令字必为ICW2, 因为初始化命令字必须按照一定的
顺序输入,并且ICW1、ICW2 是必须输入的。
B、ICW2后的命令字是否为ICW3,由ICW1的D1位决定。若D1=0,则此后必为ICW2; 否则
没有ICW3。
C、此后是否为ICW4, 由ICW1的D0位决定。若D0=1, 则此后必为ICW4; 否则没有ICW4。
D、若不是以上三者,则必为0CW1。
好了,估计你也看累了,感谢阅读,若有错误或疑问,请欢迎评论私信,最后附上参考的一个博客,总结非常详细,关于8259A的相关寄存器配置。同时,感谢该博主的分享。详解8259A_车子(chezi)-CSDN博客_8259