第十二章 内中断
引言和简介
1.中断是CPU处理外部突发事件的一个重要技术
2.它能使CPU在运行过程中对外部事件发出的中断请求及时地进行处理,处理完成后又立即返回断点,继续进行CPU原来的工作。
3.引起中断的原因【即:发出中断请求的来源叫作中断源】
4.根据中断源的不同,可以把中断分为:【软件中断】和【硬件中断】两大类, 而硬件中断又可以分为【外部中断】和【内部中断】两类
12.1 内中断的产生
1.外部中断一般是指计算机外设发出的中断请求,如:键盘中断、打印机中断、定时器中断。
外部中断是可以屏蔽的中断,也就是说,利用中断控制器可以屏蔽这些外部设备的中断请求。
2.内部中断是指因硬件出错(如突然掉电、奇偶校验错等)或运算出错(除数为零、运算溢出、单步中断)所引起的中断。
内部中断是不可屏蔽的中断
3.软件中断其实并不是真正的中断,他们只是可被调用执行的一般程序,
DOS的系统功能调用(int 21h)都是软件中断
4.CPU为了处理并发的中断请求,规定了中断的优先权,优先权由高到低的顺序是:
1.除法错、溢出中断、软件中断
2.不可屏蔽中断
3.可屏蔽中断
4.单步中断
12.2 中断处理程序
1.CPU的设计者必须在中断信息和其处理程序的入口地址之间建立某种联系,
使得CPU根据中断信息可以找到要执行的处理程序。
2.中断信息中包含有表示中断的类型码。根据CPU的设计,中断类型码的作用
就是用来定位中断处理程序的。
3.CPU用8位的中断类型码通过中断向量表找到相应的中断处理程序的入口地址,
即中断类型码是中断向量在中断向量表中的索引
12.3 中断向量表
【中断向量表就是中断向量的列表】
1.中断向量表在内存中保存,其中存放着256个【2^8,8位中断类型码】中断源所对应的中断处理程序的入口, 对于8086PC机,中断向量表指定放在内存地址0处
2.从0:0000 - 0:03FFh的1024个字节【256*4,物理地址使用段地址和偏移地址存放,需要4个字节】中存放着中断向量表,一般情况下,0:200h - 0:2FFh(256字节的安全空间,对应的中断向量表都是空的)
12.4 中断过程
1.可以用中断类型码,在中断向量表中找到中断处理程序的入口
找到这个入口地址的最终目的是用它设置cs和ip,使CPU执行中断处理程序
2.用中断类型码找到中断向量,并用它设置cs和ip,这个工作时由CPU的硬件自动完成的
CPU硬件完成这个工作的过程被称为【中断过程】
3.中断过程
8086CPU的中断过程
1.(从中断信息中)取得中断类型码
2.标志寄存器的值入栈(保护标志位)
3.设置标志寄存器的第8位TF和第9位IF设置为0(后面讲解本步的目的)
4.cs内容入栈
5.ip内容入栈
6.从内存地址为中断类型码*4和中断类型码*4+2的两个子单元中
读取中断处理程序的入口地址设置cs和ip
4.使用汇编语言描述中断过程,如下
1.取得中断类型码N
2.pushf
3.TF=0,IF=0
4.push cs
5.push ip
6.(ip)=(N*4),(cs)=(N*4+2)
12.5 中断处理程序
1.由于CPU随时都可能检测到中断信息,也就是说,CPU随时都可能执行中断处理程序,
所以,中断处理程序必须一致存储在内存某段空间中
2.而中断处理程序的入口地址,即【中断向量】,必须存储在对应的中断向量表表项中
3.中断处理程序的编写方法和子程序的比较类似,下面是常规的步骤
1.保存用到的寄存器
2.处理中断
3.恢复用到的寄存器
4.用iret指令返回,语法描述为
pop ip
pop cs
popf
iret通常和硬件自动完成的中断过程配合使用
iret指令执行后,CPU回到执行中断处理程序前的执行点继续执行程序
12.6 除法错误中断的处理
当CPU执行div等除法指令的时候,如果发生了除法溢出错误,将产生中断类型码为0的终端信息
CPU将检测到这个信息,然后引发中断程序,转去执行0号中断对应的中断处理程序
例如:
mov ax 1000h
mov bh,1
div bh
此程序会产生溢出,高8位不能存放16位
运行之后,会显示
12.7 编程处理0号中断
现在重新编写一个0号中断处理程序,它的功能是在屏幕中间显示“Welcome to here!”的广告词,然后返回到操作系统,0:0000 - 0:03FFh的1kb向量表
把中断处理程序do0放到安全空间中0:200h - 0:2FFh(256字节的安全空间,对应的中断向量表都是空的)
中断程序的框架,0号中断类型码N是0,(ip)=(N*4),do0程序的偏移地址200h存放在ip为0000:0000字单元中,(cs)=(N*4+2),do0程序的段地址0存放在cs0000:0002字单元中
assume cs:code
code segment
start:
;do0安装程序
mov ax,cs
mov ds,ax
mov si,offset do0;设置ds:si指向源地址
mov ax,0
mov es,ax
mov di,200h;设置es:di指向目的地址
mov cx,offset do0end - offset do0;do0的长度;设置cx传输长度
cld ;设置传输方向为正
rep movsb ;正向移动程序do0
;设置中断向量表
mov ax,0
mov cs,ax
mov word ptr es:[0*4],200h ;do0程序的偏移地址
mov word ptr es:[0*4+2],0 ;do0程序的段地址
mov ax,4c00h
int 21h
do0: ;显示字符串的do0中断处理程序
jmp short do0start
db 'welcome to here!' ;字符串没有放在dataseg中,因为不安全可能由于错误程序被覆盖
do0start :
mov ax,cs
mov ds,ax
mov si,202h ;设置ds:si指向字符串,因为do0第一条jmp指令占2字节
mov ax,0b800h
mov es,ax
mov di,12*160+36*2 ;设置es:di指向屏幕中间位置
mov cx,16 ;字符长度
s:
mov al,[si]
mov es:[di],al
inc si
add di,1
mov al,02h ;设置颜色
loop s
mov ax,4c00h
int 21h
do0end:nop
code ends
end start
12.8 安装
计算中断程序的长度:offset 标号1-offset 标号2
在代码段中存放数据
mov ax,cs
mov ds,ax
mov si,offset do0;设置ds:si指向源地址
mov ax,0
mov es,ax
mov di,200h;设置es:di指向目的地址
mov cx,offset do0end - offset do0;do0的长度;设置cx传输长度
cld ;设置传输方向为正
rep movsb ;正向移动程序do0
12.9 do0
do0: ;显示字符串的do0中断处理程序
jmp short do0start
db 'welcome to here!' ;字符串没有放在dataseg中,因为不安全可能由于错误程序被覆盖
do0start :
mov ax,cs
mov ds,ax
mov si,202h ;设置ds:si指向字符串,因为do0第一条jmp指令占2字节
mov ax,0b800h
mov es,ax
mov di,12*160+36*2 ;设置es:di指向屏幕中间位置
mov cx,16 ;字符长度
s:
mov al,[si]
mov es:[di],al
inc si
add di,1
mov al,02h ;设置颜色
loop s
12.10 设置中断向量
mov ax,0
mov cs,ax
mov word ptr es:[0*4],200h ;do0程序的偏移地址
mov word ptr es:[0*4+2],0 ;do0程序的段地址
12.11 单步中断
如果检测到标志寄存器的tf位为1,则产生单步中断,引发中断过程
cpu执行1号中断程序
12.12 响应中断的特殊情况
在执行完向ss寄存器传送数据的指令号,检查到中断信号,cpu也不会响应。
因为,ss:sp指向栈顶,中断过程需要向栈压入标志寄存器、cs、ip的值。
所以ss改变,而sp没变会引起错误。
ss和sp的操作必须是连续的。也就是第三章【实验二】提到的下一条指令执行的消失。