概述
内中断
“中断信息”是要求CPU马上进行某种处理,并向所要进行的该种处理提供了必备的参数的通知信息。
12.1 内中断的产生
当CPU内部有下面的情况发生的时候,将产生相应的中断信息。
- 除法错误
- 单步执行
- 执行into指令
- 执行int指令
8086CPU用称为中断类型码的数据来标识中断信息的来源。中断类型码为一个字节型数据,可以表示256种中断信息的来源。
- 除法错误:0
- 单步执行:1
- 执行into指令:4
- 执行int指令:该指令的格式为
int n
,指令中的n为字节型立即数,是提供给CPU的中断类型码。
12.2 中断处理程序
CPU收到中断信息后,需要对中断信息进行处理。而如何对中断信息进行处理,可以由我们编程决定。
CPU的设计者必须在中断信息和其处理程序的入口地址之间建立某种联系,使得CPU根据中断信息可以找到要执行的处理程序。
12.3 中断向量表
中断向量表的内存中保存,其中存放着256个中断源所对应的中断处理程序的入口,如图。
可见,CPU只要知道中断类型码,就可以将中断类型码作为中断向量表的表项号,定位相应的表项,从而得到中断处理程序的入口地址。
中断向量表在内存中存放,对于8086CP机,中断向量表指定放在内存地址0处。从内存0000:0000到0000:03FF的1024个单元中存放着中断向量表。
对于8086CPU,这个入口地址包括段地址和偏移地址,所以一个表项占两个字,高地址字存放段地址,低地址字存放偏移地址。
检测点 12.1
(1)用Debug查看内存,情况如下:
0000:0000 68 10 A7 00 8B 01 70 00-16 00 9D 03 8B 01 70 00
则3号中断源对应的中断处理程序入口地址为:0070:018B。
(2)存储N号中断源对应的中断处理程序入口的偏移地址的内存单元的地址为:0000:N*4.
存储N号中断源对应的中断处理程序入口的段地址的内存单元的地址为:0000:N*4+2.
12.4 中断过程
从上面的讲解中,我们知道,可以用中断类型码,在中断向量表中找到中断处理程序的入口。找到这个入口地址的最终目的是用它设置CS和IP,使CPU执行中断处理程序。用中断类型码找到中断向量,并用它设置CS和IP,这个工作是由CPU的硬件自动完成的。CPU硬件完成这个工作的过程被称为中断过程。
下面是8086CPU在收到中断信息后,所引发的中断过程。
- (从中断信息中)取得中断类型码
- 标志寄存器的值入栈(因为在中断过程中要改变标志寄存器的值,所以先将其保存在栈中)
- 设置标志寄存器的第8位TF和第9位IF的值为0(这一步的目的后面将介绍)
- CS的内容入栈
- IP的内容入栈
- 从内存地址为 中断类型码∗4 中 断 类 型 码 ∗ 4 和 中断类型码∗4+2 中 断 类 型 码 ∗ 4 + 2 的两个字单元中读取中断处理程序的入口地址设置IP和CS
更简洁的描述中断过程,如下:
- 取得中断类型码N
- pushf
- TF=0,IF=0
- push CS
- push IP
- (IP)=(N∗4),(CS)=(N∗4+2) ( I P ) = ( N ∗ 4 ) , ( C S ) = ( N ∗ 4 + 2 )
12.5 中断处理程序和iret指令
CPU随时都可能只想中断处理程序,所以中断处理程序必须一直存储在内存某段空间中。而中断处理程序入口地址,即中断向量,必须存储在对应的中断向量表表项中。
中断处理程序的编写方法和子程序的比较相似,下面是常规的步骤:
- 保存用到的寄存器
- 处理中断
- 恢复用到的寄存器
- 用iret指令返回
iret指令的功能用汇编语法描述为:
pop IP
pop CS
popf
12.6 除法错误中断的处理
当CPU执行div发生了除法溢出错误,将产生中断类型码为0的中断信息,CPU将检测到这个信息,然后引发中断过程,转去执行0号中断所对应的中断处理程序。
12.7 编写处理0号中断
这里略过,自己看,内容很细致。
12.8 安装
其实就是将代码复制到程序的某个地方,这里也略过!贴上代码。
assume cs:code
code segment
start:
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
;设置cx为传输长度
cld
;设置传输方向为正
rep movsb
;复制
设置中断向量表
mov ax,4c00h
int 21h
do0:
显示字符串"overflow!"
mov ax,4c00h
int 21h
do0end:
nop
code ends
end start
12.9 do0
显示字符串”overflow!”的子程序。不能够再去一个data的数据区,因为可能会被覆盖,所以应该如下:
12.10 设置中断向量
最重要点的一点:
mov ax,0
mov es,ax
mov word ptr es:[0*4],200h
;低地址字
mov word ptr es:[0*4+2],0
;高地址字
12.11 单步中断
基本上,CPU在执行完一条指令之后,如果检测到标志寄存器的TF位为1,则产生单步中断,引发中断过程。单步中断的中断类型码为1,则它所引发的中断过程如下。
- 取得中断类型码1
- 标志寄存器入栈,TF、IF设置为0
- CS、IP入栈
- (IP)=(1∗4),(CS)=(1∗4+2) ( I P ) = ( 1 ∗ 4 ) , ( C S ) = ( 1 ∗ 4 + 2 )
注意,第2步很重要,因为如果不将TF位置0,则将陷入一个永远不能结束的循环。因为单步中断将引发单步中断的中断程序,而单步中断的中断程序将引发单步中断程序中的中断程序…
于是中断过程如下:
- 取得中断类型码N
- 标志寄存器入栈,TF=0、IF=0
- CS、IP入栈
- (IP)=(N∗4),(CS)=(N∗4+2) ( I P ) = ( N ∗ 4 ) , ( C S ) = ( N ∗ 4 + 2 )
12.12 响应中断的特殊情况
一般情况下,CPU在执行完当前指令后,如果检测到中断信息,就响应中断程序,引发中断过程。可是,在有些情况下,CPU在执行完当前指令后,即便是发生中断,也不会响应。
比如,在执行完向ss寄存器传送数据的指令后,即便发生中断,CPU也不会响应。这样做的主要原因是,ss:sp联合指向栈顶,而对它们的设置应该连续完成。如果执行完设置ss的指令后,CPU响应中断,引发中断过程,要在栈中压入标志寄存器、CS和IP的值。而ss改变,ss:sp指向的不是正确的栈顶,将引发错误。所以CPU在执行完设置ss的指令后,不响应中断。这给连续设置ss和sp指向正确的栈顶提供了一个时机。即,我们应该利用这个特性,将设置ss和sp的指令连续存放,使得设置sp的指令紧接着设置ss的指令执行,而在此之间,CPU不会引发中断过程。
实验12 编写0号中断的处理程序
分析:
assume cs:codesg
codesg segment
start:
ds:[si]是源地址
0:200是目的地址
cx是长度
rep movsb
mov ax,0
mov es,ax
mov word ptr es:[0*4],200h
mov word ptr es:[0*4],0
mov ax,10
div 0
mov ax,4c00h
int 21h
do0:
db "divide error!"
do0start:
在屏幕中间显示"divide error!"
mov ax,4c00h
int 21h
do0end:
nop
codesg ends
end start
实际代码:
assume cs:codesg
codesg segment
start:
mov ax,cs
mov ds,ax
mov si,offset do0
;源地址
mov ax,0
mov es,ax
mov di,200h
;目的地址
mov cx,offset do0end-offset do0 ;长度
cld
;方向
rep movsb
;安装
mov ax,0
mov es,ax
mov word ptr es:[0*4],200h
mov word ptr es:[0*4+2],0
;设置中断向量表
mov ax,10
mov dx,0
div dx
mov ax,4c00h
int 21h
do0:
jmp short do0start
db "divide error!"
;字符串
do0start:
mov ax,cs
mov ds,ax
mov si,202h
mov ax,0b800h
mov es,ax
mov di,12*160+36*2
mov cx,13
s:
mov al,[si]
mov es:[di],al
inc si
add di,2
loop s
;显示字符串
mov ax,4c00h
;退出程序
int 21h
do0end:
nop
codesg ends
end start
实验结果:
最后
以上就是内向小甜瓜为你收集整理的内中断---汇编学习笔记内中断的全部内容,希望文章能够帮你解决内中断---汇编学习笔记内中断所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复