根据您的个性需求进行定制 先人一步 抢占小程序红利时代
目录
引言
12.1 内中断的产生
12.2 中断处理程序
12.3 中断向量表
检测点12.1
12.4 中断过程
12.5 中断处理程序和iret指令
12.6 除法错误中断的处理
12.7 编程处理0号中断
12.8 安装
12.9 do0
12.10 设置中断向量
12.11 单步中断
12.12 响应中断的特殊情况
任何一个通用的CPU,比如8086,都具备一种能力,可以在执行完当前正在执行的指令之后,检测到从CPU外部发送过来的或内部产生的一种特殊信息,并且可以立即对所接收到的信息进行处理。这种特殊的信息,我们可以称其为:中断信息。中断的意思是指,CPU不再接着(刚执行完的指令)向下执行,而是转去处理这个特殊信息。
“中断信息“是要求CPU马上进行某种处理,并向所要进行的该种处理提供了必备的参数的通知信息。
中断信息可以来自CPU的内部和外部。
12.1 内中断的产生对于8086CPU,当CPU内部有下面的情况发生的时候, 将产生相应的中断信息:
(1)除法错误,比如,执行div指令产生的除法溢出;
(2)单步执行;
(3)执行into指令;
(4)执行int指令。
不同的信息需要进行不同的处理。
CPU首先要知道所接接收的中断信息的来源。所以中断信息中必须包含识别来源的编码。8086CPU用称为中断类型码的数据来标识中断信息的来源。中断类型码为一个字节型数据,可以表示256种中断信息的来源。
我们将产生中断信息的事件,即中断信息的来源,简称为中断源。
上述的四种中断源,在8086CPU中的中断类型码如下:
(1)除法错误:0
(2)单步执行:1
(3)执行into指令:4
(4)执行int指令,该指令格式为int n,指令中的n为字节型立即数,是提供给CPU的中断类型码。
12.2 中断处理程序用来处理中断信息的程序被称为中断处理程序。一般来说需要对不同的中断信息编写不同的处理程序。
CPU在收到中断信息后,应该转去执行该中断信息的处理程序。若要8086CPU执行某处的程序,就要将CS:IP指向它的入口(即程序第一条指令的地址)。
12.3 中断向量表CPU用8位的中断类型码通过中断向量表找到相应的中断处理程序的入口地址。
中断向量,就是中断处理程序的入口地址。中断向量表,就是中断处理程序入口地址的列表。
中断向量表在内存中保存,其中存放这256个中断源所对应的中断处理程序的入口。
CPU只要知道了中断类型码,就可以将中断类型码作为中断向量表的表项号,定位相应的表项,从而得到中断处理程序的入口地址。
中断向量表在内存中存放,对于8086PC机,中断向量表指定放在内存地址0处。从内存0000:0000到0000:03FF的1024个单元中存放这中断向量表。一个表项存放一个中断向量,也就是一个中断处理程序的入口地址,对于8086CPU,这个入口地址包括段地址和偏移地址,所以一个表项占两个字,高地址字存放段地址,低地址字存放偏移地址。
检测点12.1用中断类型码找到中断向量,并用它设置CS和IP,这个工作是由CPU的硬件自动完成的。CPU硬件完成这个工作的过程被称为中断过程。
CPU收到中断信息后,要对中断信息进行处理,首先将引发中断过程。硬件在完成中断过程后,CS:IP将指向中断处理程序的入口,CPU开始执行中断处理程序。
CPU在执行完中断处理程序后,应该返回原来的执行点继续执行下面的指令。所以在中断过程中,在设置CS:IP之前,还要将原来的CS和IP值保存起来。
下面是8086CPU在收到中断信息后,所引发的中断过程:
(1)(从中断信息中)取得中断类型码;
(2)标志寄存器的值入栈(因为在中断过程中要改变标志寄存器的值,所以先将其保存在栈中);
(3)设置标志寄存器的第8位TF和第9位IF的值为0;
(4)CS的内容入栈;
(5)IP的内容入栈;
(6)从内存地址为中断类型码*4和中断类型码*4+2的两个字单元中读取中断处理程序的入口地址设置IP和CS。
更简洁地描述中断过程:
(1)取得中断类型码N;
(2)pushf
(3)TF=0,IF=0
(4)push CS
(5)push IP
(6)(IP)=(N*4),(CS)=(N*4+2)
在最后一步完成后,CPU开始执行由程序员编写的中断处理程序。
12.5 中断处理程序和iret指令CPU随时都有可能执行中断处理程序,所以中断处理程序必须一致存储在内存某段空间之中。而中断处理程序的入口地址,即中断向量,必须存储在对应的中断向量表表项中。
中断处理程序的编写方法常规步骤:
(1)保存用到的寄存器;
(2)处理中断;
(3)恢复用到的寄存器;
(4)用iret指令返回;
iret指令的功能用汇编语法描述为:
pop IP
pop CS
popf
iret通常和硬件自动完成的中断过程配合使用。在中断过程中,寄存器入栈的顺序是标志寄存器、CS、IP,而iret的出栈顺序使IP、CS、标志寄存器,刚好和其相对应,实现了用执行中断处理程序前的CPU现场恢复标志寄存器和CS、IP的工作。iret指令执行后,CPU回到执行中断处理程序前的执行点继续执行程序。
12.6 除法错误中断的处理当CPU执行div等除法指令的时候,如果发生了除法溢出错误,将产生中断类型码为0的中断信息,CPU将检测到这个信息,然后引发中断过程,转去执行0号中断所对应的中断处理程序。
mov ax,1000h
mov bh,1
div bh
当CPU执行div bh时,发生了除法溢出错误,产生0号中断信息,从而引发中断过程,CPU执行0号中断处理程序。我们从图中可以看出系统的0号中断处理程序的功能:显示提示信息”Divide overflow“后,返回到操作系统中。
12.7 编程处理0号中断我们可以改变0号中断处理程序的功能,即重新编写一个0号中断处理程序,它的功能是在屏幕中间显示“overflow!”,然后返回到操作系统,如图所示。
当CPU执行div bh时,发生了除法溢出错误,产生0号中断信息,引发中断过程,CPU执行我们编写的0号中断处理程序。在屏幕中间显示提示信息“overflow!”后,返回到操作系统中。
编程:当发生除法溢出时,在屏幕中间显示“overflow!”,返回DOS。
分析:
(1)当发生除法溢出时,产生0号中断信息,从而引发中断过程。
此时,CPU将进行以下工作:
①取得中断类型码0;
②标志寄存器入栈,TF、IF设置为0;
③CS、IP入栈;
④(IP)=(0*4),(CS)=(0*4+2)
(2)当中断0发生时,CPU将转去执行中断处理程序。
按如下步骤编写中断处理程序,当中断0发生时,即可显示“overflow!”。
①相关处理;
②向显示缓冲区送字符串“overflow!”;
③返回DOS。
我们将这段程序称为:do0。
(3)do0应存放在内存中。因为除法溢出随时可能发生,CPU随时都可能将CS:IP指向do0的入口,执行程序。
找到一块别的程序不会用到的内存区,将do0传送到其中。
内存0000:0000~0000:03FF,大小为1KB的空间是系统存放中断处理程序入口地址的中断向量表。8086支持256个中断,但实际上系统中要处理的中断时间远没有256个。所以在中断向量表中有许多单元都是空的。因此可以用中断向量表中的空闲单元来存放我们的程序。一般情况下,从0000:0200~0000:02FF的256个字节的空间所对应的中断向量表项都是空的。
结论:我们可以将do0传送到0000:0200处。
(4)将中断处理程序do0放到0000:0200后,若要使得除法溢出发生的时候,CPU转去执行do0,则必须将do0的入口地址,即0000:0200登记在中断向量表的对应表项中。因为除法溢出对应的中断类型码为0,它的中断处理程序的入口地址应该从0*4地址单元开始存放,段地址存放在0*4+2字单元中,偏移地址存放在0*4字单元中。也就是说要将do0的段地址0存放在0000:0002字单元中,将偏移地址200H存放在0000:0000字单元中。
总结:
(1)编写可以显示“overflow!”的中断处理程序:do0;
(2)将do0送入内存0000:0200处;
(3)将do0的入口地址0000:0200存储在中断向量表0号表项中。
程序的框架如下:
assume cs:code
code segment
start: do0安装程序
设置中断向量表
mov ax,4c00h
int 21h
do0: 显示字符串“overflow!”
mov ax,4c00h
int 21h
code ends
end start
程序分为两部分:
(1)安装do0,设置中断向量的程序;
(2)do0。
程序执行时,do0的代码是不执行的,它只是作为do0安装程序所要传达的数据。程序执行时首先执行do0安装程序,将do0的代码复制到内存0:200处,然后设置中断向量表,将do0的入口地址,即偏移地址200H和段地址0,保存在0号表项中。这两部分工作完成后,程序就返回了。程序的目的就是在内存0:200处安装do0的代码,将0号中断处理程序的入口地址设置为0:200。do0的代码虽然在程序中,却不在程序执行的时候执行。它是在除法溢出发生的时候才得以执行的中断处理程序。
do0变成0号中断的中断处理程序的过程:
(1)程序在执行时,被加载到内存中,此时do0的代码在程序所在的内存空间中,它只是存放在程序的代码段中的一段要被传送到其他单元中的数据,我们不能说它是0号中断的中断处理程序;
(2)程序中安装do0的代码执行完后,do0的代码被从程序的代码段中复制到0:200处。此时,我们也不能说它是0号中断的中断处理程序,它只不过是存放在0:200处的一些数据;
(3)程序中设置中断向量表的代码执行完后,在0号表项中填入了do0的入口地址0:200,此时0:200处的信息,即do0的代码,就变成了0号中断的中断处理程序。因此当除法溢出(即0号中断)发生时,CPU将执行0:200处的代码。
12.8 安装将do0的代码送入0:200处:
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 ;设置cs为传输长度
cld ;设置传输方向为正
rep movsb
设置中断向量表
mov ax,4c00h
int 21h
do0: 显示字符串“overflow!”
mov ax,4c00h
int 21h
do0end:nop
code ends
end start
用rep movsb指令的时候要确定的信息:
(1)传送的原始位置,段地址:code,偏移地址:offset do0;
(2)传送的目的位置:0:200;
(3)传送的长度:do0部分代码的长度;
(4)传送的方向:正向。
“-”是编译器识别的运算符号,编译器可以用它来进行两个常数的减法。(汇编编译器可以处理表达式)
比如,指令:mov ax,8-4,被编译器处理为指令mov ax,4。
12.9 do012.10 设置中断向量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 ;设置cs为传输长度
cld ;设置传输方向为正
rep movsb
设置中断向量表
mov ax,4c00h
int 21h
do0: jmp short do0start
db "overflow!"
do0start: mov ax,cs;
mov ds,ax
mov si,202h ;设置ds:si指向字符串
mov ax,0b800h
mov es,ax
mov di,12*160+36*2 ;设置es:di指向显存空间的中间位置
mov cx,9
s: mov,al,[si]
mov es:[di],al
inc si
add di,2
loop s
mov ax,4c00h
int 21h
do0end:nop
code ends
end start
下面进行将do0的入口地址0:200,写入中断向量表的0号表项中,使do0成为0号中断的中断处理程序。
0号表项的地址为0:0,其中0:0字单元存放偏移地址,0:2字单元存放段地址。程序如下:
12.11 单步中断mov ax,0
mov es,ax
mov word ptr es:[0*4],200h
mov word ptr es:[0*4+2],0
基本上,CPU在执行完一条指令后,如果检测到标志寄存器的TF位为1,则产生单步中断,引发中断过程。单步中断的中断类型码为1,则它所引发的中断过程如下:
(1)取得中断类型码1;
(2)标志寄存器入栈,TF、IF设置为0;
(3)CS、IP入栈;
(4)(IP)=(1*4),(CS)=(1*4+2)
如上所述,如果TF=1,则执行一条指令后,CPU就要转去执行1号中断处理程序。
在进入中断处理程序之前,设置TF=0,从而避免CPU在执行中断处理程序的时候发生单步中断。
CPU提供单步中断功能的原因就是:为单步跟踪程序的执行过程,提供了实现机制。
12.12 响应中断的特殊情况一般情况下,CPU在执行完当前指令后,如果检测到中断信息,就响应中断,引发中断过程。但在有些情况下,CPU在执行完当前指令后,即便是发生中断,也不会响应。
在执行完ss寄存器传送数据的指令后,即便是发生中断,CPU也不会响应。这样做的主要原因是:ss:sp联合指向栈顶,而对它们的设置应该连续完成。因此我们将设置ss和sp的指令连续存放,是的设置sp的指令紧接着设置ss的指令执行,在此之间,CPU不会引发中断过程。
比如,我们要将栈顶设置为1000:0,应该:
mov ax,1000h
mov ss,ax
mov sp,0
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧