中断与中断处理程序
4.6.1中断的概念:
当外设发生一些紧急情况需要CPU立即处理的时候,由外设通过专门的连线与芯片向CPU发出中断请求,告诉CPU;CPU根据送来的中断类型码(见下文)知道外部设备发生什么情况,到中断向量表中找到对应的中断处理程序的入口地址,然后,直接跳转到该处执行;这个过程称为中断。
在8086系列的指令系统中把上节所讲解的内容也包含在中断的概念中了,称之为软件中断。
1.中断的分类:
8086系统的中断总共有256个,分成软件中断与硬件中断两大类。
1)软件中断:
类似于上节所讲解的DOS功能调用,软件中断是利用中断指令在源程序中事先编写好的,当程序执行到此的时候,象子程序调用一样,CPU转移到对应的中断处理程序中去执行,形式见例4.25。
注意:软件中断与一般的子程序是不同的,两者的执行情况不一样,两者的地位也不一样。
中断一般分成两大类:
1)软件中断:
象上节所介绍的,这类中断是在程序中利用中断指令编写好的,当程序运行到此时,与一个子程序一样来进行调用,它是可以预测的。
例4.23:
;…………源程序…………
CODE SEGMENT
ASSUME CS:CODE
START:…
INT nH
CODE ENDS
END START
2)硬件中断:
由硬件、硬件连线所引起的中断称为硬件中断,它在源程序中没有指令来执行,是不可预知的,这种中断是本节要讲解的主要内容。
硬件中断又分成可屏蔽中断与非屏蔽中断两类。两者的中断信号分别通过不同的信号线送到CPU中;CPU中的标志寄存器中的IF会影响可屏蔽中断的执行,但不影响非屏蔽中断的执行;非屏蔽中断只有一个,它的中断类型码为2号。
一般情况下,不要变动系统自身已经设置好的硬件中断,尤其是非屏蔽中断。
2.中断类型码与中断向量表:
为了使CPU能够分别出每一个中断,给每个中断一个编号,称为中断类型码,简称中断号。
每个中断类型码与一个存放它的中断处理程序的入口地址的存储区域相对应,这个地址称为中断向量,显然每个存储区域占四个存储空间(4bit);这些存储空间是集中放在内存的最开始处,称为中断向量表。形式参见图4.5。
图4.5
3.硬件中断的执行:
软件中断的执行情况在形式上与一般的子程序类似,但是硬件中断的执行是我们前面所没有遇到过的。
当外部设备发生情况的时候,会通过某种信号线输入到CPU中,CPU会根据得到的中断号在中断向量表中查找到对应的中断入口地址,然后跳转到该处执行。这些步骤都是计算机硬件自动完成的,程序员只能在设置中断处理程序和中断向量的时候编写相应的程序。
具体的硬件响应过程在后面的《微机原理》课程中再详细介绍。
4.6.2中断的设置:
1.中断向量的设置:
根据前面所讲解的内容,知道:如果将中断向量表中的某个向量的值该换成其它的值,那么当遇到中断的时候,CPU会到修改过后的地址起去执行它认为的中断处理程序。通过这种形式就可以设置中断向量。
但是,这种形式的设置,容易影响其它存储空间,有可能产生严重的后果。我们可以使用25H号DOS功能调用进行设置。注意,如果只是进行调试性的设置,应该利用35H号DOS功能调用得到原来的值并保存起来,以便恢复。
例4.24:
修改1CH号中断的中断向量。
;…………源程序…………
CODE SEGMENT
ASSUME CS:CODE
START:…
…
;利用35H号中断调用得到原来的中断向量并保存
MOV AL,1CH
MOV AH,35H
INT 21H
PUSH ES
PUSH BX
PUSH DS
PUSH DX
;设置新的中断向量
MOV DS,SEG NEWINT1CH
MOV DX,OFFSET NEWINT1CH
MOV AL,1CH
MOV AH,25H
INT 21H
…
POP DX
POP DS
;恢复老的中断向量
POP BX
POP ES
MOV AL,1CH
MOV AH,25H
INT 21H
…
…
;中断处理程序
NEWINT1CH:
…
…
CODE ENDS
END START
2.中断程序的编写:
中断程序的编写与一般子程序形式类似,但是必须是在设置中断向量的时候,已经编译完毕的机器代码。
例4.27:
显示系统时钟。
分析:计算机在启动的时候,将系统的定时器(可以计算时间的一种芯片)初始化为每隔约55毫秒向CPU发出一个中断请求;CPU响应定时中断是执行8H号中断处理,而在BIOS提供的8H中断处理程序中有一条中断指令“INT 1CH”,所以每秒钟系统会调用18.2次ICH号中断处理程序;实际上,系统的1CH号中断处理程序没有做任何工作,只是一条中断返回指令“IRET”,这里就可以编写新的ICH号中断处理程序替换原来的。
在新的ICH号中断处理程序中安排一个计数器,记录调用该处理程序的次数,当达到18次时,就在屏幕右上角显示当前的系统时间,并将计数器清零。
获取当前系统时间是调用1AH号中断的2号功能完成,该功能在CH、CL、DH寄存器中分别返回系统时间的时、分、秒的BCD码;将BCD转换成对应的十进制数的ASCII码后,利用I/O程序显示出来。
程序如下:
;…………源程序…………
;……………………………
;…处理程序的常量定义…
COUNT_VAL=18 ;每隔18次“滴答”一次
DPAGE =0 ;显示页号
ROW =0 ;显示的行号
COLUMN =80-BUFF_LEN ;显示开始的列号
COLOR =07H ;显示的属性
;……………………………
;…………代码段…………
CODE SEGMENT
ASSUME CS:CODE,DS:CODE
;在代码段中也可以定义变量,即数据段与代码段重叠
COUNT DW COUNT_VAL ;计数器
HHHH DB ?,?,‘:’ ;时
MMMM DB ?,?,‘:’ ;分
SSSS DB ?,? ;秒
BUFF_LEN =$-OFFEST HHHH ;显示的字符长度
COUSOR DW ? ;原光标位置
;……中断处理程序代码……
;这里编写的新的中断处理程序,不是程序开始执行的位置
;
NEW1CH:
CMP CS:COUNT,0 ;是否计数到0
JZ NEXT ;如果到时间,则显示
DEC CS:COUNT ;计数器减一
IRET
NEXT:
;因为当计数器为0的时候才执行此段代码,所以计数器重新赋值
MOV CS:COUNT,COUNT_VAL
;
STI
;保存寄存器的原值
PUSH DS
PUSH ES
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH SI
PUSH BP
;对DS、ES赋值
PUSH CS
POP DS
PUSH DS
POP ES
;利用子程序得到系统时间,并保存在约定的存储空间中
CALL GET_TIME
;
MOV BH,DPAGE
;得到原来的光标位置,并保存在COURSOR
MOV AH,3
INT 10H
MOV CURSOR,DX
;显示时间
MOV BP,OFFEST HHHH;时、分、秒合成一个字符串
MOV BH,DPAGE
MOV DH,ROW
MOV DL,COLUMN
MOV BL,COLOR
MOV CX,BUFF_LEN
MOV AL,0
MOV AH,13H
INT 10H
;恢复原光标
MOV DH,DPAGE
MOV AH,2
INT 10H
;恢复寄存器原值
POP BP
POP SI
POP DX
POP CX
POP BX
POP AX
POP ES
POP DS
;新的1CH号中断处理程序结束
IRET
;
;……GET_TIME子程序……
;利用1AH号中断的2H功能调用得到系统时间
GET_TIME PROC
;1AH号中断的2H功能
MOV AH,2
INT 1AH
;将“小时”放在AL中并利用子程序转换成ASCII码后保存在HHHH中
MOV AL,CH
CALL TIME_TO_ASCII
XCHG AH,AL
MOV WORD PTR HHHH,AX
;得到“分”并转换、保存
MOV AL,DH
CALL TIME_TO_ASCII
XCHG AH,AL
MOV WORD PTR MMMM,AX
;得到“秒”并转换、保存
MOV AL,DH
CALL TIME_TO_ASCII
XCHG AH,AL
MOV WORD PTR SSSS,AX
;子程序结束
RET
GET_TIME ENDP
;
;…TIME_TO_ASCII子程序…
;将约定的寄存器中的值转换成ASCII码
TIME_TO_ASCII PROC
;
MOV AH,AL
;将AL中BCD码的高4位清零,得到低4位
AND AL,0FH
;利用移位指令,将AH中BCD码高4位移到低4位
SHR AH,1
SHR AH,1
SHR AH,1
SHR AH,1
;AH 30H,AL 30H后得到相应的ASCII码
ADD AX,3030H
;子程序结束
RET
TIME_TO_ASCII ENDP
;……………………………
;…………主程序…………
;定义一个双字变量用来保存原来的1CH号中断向量
OLD1CH DD ?
;程序实际开始位置
START:
;对DS赋值,DS与CS段重叠
PUSH CS
POP DS
;得到原来的1CH号中断向量
MOV AL,1CH
MOV AH,35H
INT 21H
;保存原来的中断向量
MOV WORD PTR OLD1CH,BX
MOV WORD PTR OLD1CH 2,ES
;利用25H号DOS功能调用设置新的1CH号中断向量
;因为DS已经指向NEW1CH程序的段值,所以可以不再赋值
MOV DX,OFFSET NEW1CH
MOV AX,251CH
INT 21H
;程序执行其它工作,注意这里没有调用NEW1CH程序
…
;假设,其它工作有一项是等待按键
MOV AH,0
INT 16H
;恢复原来的中断向量的值
LDS DX,OLD1CH
MOV AX,251CH
INT 21H
;利用4CH号DOS功能调用,正常退出程序
MOV AH,4CH
INT 21H
;程序结束
CODE ENDS
END START