汇编语言学习第十二章-内中断

本博文系列参考自<<汇编语言>>第三版,作者:王爽


当CPU执行完当前的任务的时候,收到来CPU外部或者内部发来的一种信息,转而不继续执行当前信息,而是立即对外部或者内部的信息进行处理,这样一种来自CPU外部或者内部的信息称为中断信息。中断的意思是指不再继续当前的任务执行下去,而是转而执行外部的或者内部的这个特殊信息。
中断信息可以来自CPU内部或者CPU外部,即内中断或外中断。本文主要介绍内中断。

12.1内中断的产生
以下四种情况将产生内部中断信息:
(1) 除法错误,比如,执行div指令产生的除法溢出
(2)单步执行
(3)执行Into指令
(4)执行int指令

这四种情况将产生中断信息。不同的中断信息需要进行不同的处理。要进行区别处理,CPU要对中断的来源进行区分。所以中断信息应该包含识别来源的编码。8086CPU用中断类型码来标识中断的来源。中断类型码为单字节型数据,能够标识256种中断信息的来源。我们要产生中断信息的事件,即中断信息的来源,简称中断源,上述四种中断源在8086CPU中的中断类型吗为:
(1)除法错误:0
(2)单步执行:1
(3)执行into指令:4
(4)执行Int指令:int指令格式为 int n其中为中断类型码

12.2中断处理程序
cpu收到中断信息后,需要对中断信息进行处理。不同的中断信息需要进行不同的处理,即需要编写不同的中断处理程序。要使得收到中断信息后转到相应的中断处理程序进行处理,我们需要将CS:IP改为中断处理程序的入口地址进行相应的中断处理。其实中断信息中的中断类型码即是用来定位中断处理程序的。比如中断类型码为4则定位到4号中断处理程序。那么我们如何建立中断类型码与中断处理程序的段地址和偏移地址之间的关系呢?


12.3中断向量表
中断向量表即为中断向量的列表。中断向量即为中断处理程序的入口地址。中断向量表即保存着256个中断源对应的中断处理程序的入口地址,如下图所示:

CPU根据中断信息中的中断类型码在中断向量表中查找对应的中断处理程序的入口地址。
对于8086CPU,中断向量表指定放在内存的0处。从0000:0000到0000:03FF的1024个单元存放着中断向量表。8086CPU不能将中断向量表存放在别处,只能存放在此处。一个中断向量存放一个中断处理程序的入口地址,这个入口地址包括段地址和偏移地址,段地址和偏移地址分别占2个字节。所以一个中断向量占4个字节。256个中断向量表占了1024个字节。


12.4中断过程
中断过程即CPU收到中断信息后,从中断信息中获取中断类型码,然后通过中断类型码找到中断向量,最后根据中断向量设置CS:IP,进而进入中断处理程序的入口。这一过程为中断过程,由计算机硬件完成。有个问题是,在进行中断处理程序调用后需要返回到程序之前的中断点。所以在进入中断程序之前需要将CS:IP的值进行保存,然后在完成中断处理程序后需要恢复到程序之前的CS:IP。

中断过程描述如下:
(1)取得中断类型码
(2)pushf(标志寄存器的值入栈)
(3)TF=0,IF=0
(4)CS入栈
(5)IP入栈
(6)(IP)=(N*4) (CS)=(N*4+2)

12.5中断处理程序和iret指令
中断处理程序的编写与子程序类似:
(1)保存用到的寄存器
(2)处理中断
(3)恢复用到的寄存器
(4)用iret指令返回
iret指令的功能是:
pop IP
pop CS
popf
很显然iret是起到恢复现场的功能。

12.6除法错误中断的处理
当用div指令产生除法溢出中断时,中断类型码0将定位到中断向量表的第一个中断向量,然后进行相关的中断处理程序的执行。
div除法中断处理为显示“Divide overflow”同时回到操作系统。

12.7编程处理0号中断
之前的除法溢出中断是显示Divide overflow。现在我们需要自己编写除法溢出中断处理程序,该程序功能是在屏幕的中间显示字符串Divide overflow。我们自己编写的中断处理程序暂且称之为do0吧,中断处理程序可能随时被执行,我们可以使用中断向量表的区域,中断向量表0000:0000~0000:03FF这1024个字节用于存放中断向量表。但是一般情况下0000:0200~0000:02FF这一段内存对应的中断向量表是空的,我们可以将do0这段程序放到此处。所以我们在0号中断向量中可以将段地址0000H存放到内存地址为0000:0002的字单元中,将偏移地址200H存放在0000:0000的字单元中。
总结以上步骤:
1.编写do0中断处理程序
2.将do0送入内存0000:0200处
3.将入口地址0000:0200存入0号中断向量。

12.8安装
继续上一节的div除法溢出的问题,程序框架如下:

可以使用movsb指令,将do0代码送入0000:0200H处。
执行movsb指令时,要明确的信息:
1.传送的源地址。段地址:code  偏移地址: offset do0
2传送的目的地址:0000:0200H
3传送的长度:do0代码的长度
4传送的方向:正向
程序实现如下:


12.9 do0
do0的主要功能是显示字符串,实现如下;

最后,注意"Divide overflow"字符串需要定义在do0子程序中,因为该程序执行完后,程序执行分配的空间将被释放,而中断处理函数do0随时都可能执行,那么有可能存放Divide overflow"字符串的位置已经被释放或者被其他程序分配的内容所占用。所以往往把Divide overflow"字符串也定义在中断向量表空间中。

12.10设置中断向量
将中断处理程序的入口地址0000:0200H写入第0号中断向量中,其中第0号中断向量地址为0000:0000,则0000:0000字单元用于存放偏移地址0200H,0000:0002子单元用于存放段地址0000H。
程序如下:


12.11单步中断
单步中断的中断类型码为1,中断过程如下:
(1)取得中断类型吗1
(2)标志寄存器入栈,TF=0,IF=0
(3)CS,IP入栈
(4)(CS)=(N*4+2) (IP)=(N*4)

TF为1,CPU将执行单步中断,所以在进行单步中断过程应该讲TF=0;


12.12响应中断的特殊情况
有的情况下CPU在未执行完当前指令前计算有中断产生也不会响应中断。
比如我们在执行完向SS寄存器传送数据的指令后,即使发生中断,CPU也不会响应。这样做的原因是SS:SP配合指向栈顶,对它们的设置应该连续完成。在执行完设置SS后响应中断,那么此时SS改变,SP未改变,那么会指向错误的栈顶这是极其危险的。我们利用这个特性应该讲设置SS和SP的指令连续存放执行,在此之间,不会引发中断。比如我们要将栈顶设置为1000:0应为:
mov ax,1000H
mov ss,ax
mov sp,0
而不应该
mov ax,1000H
mov ss,ax
mov ax,0
mov sp,0
汇编语言学习第十二章-内中断_第1张图片


你可能感兴趣的:(汇编语言,汇编语言学习)