《汇编语言》——王爽 第12章 内中断

https://zhidao.baidu.com/question/130424698.html

任何一个通用的CPU,比如8086,都具备一种能力,可以在执行完当前正在执行的指令之后,检测到从CPU外部发送过来的或内部产生的一种特殊信息,并且可以立即对所接受到的信息进行处理。这种特殊的信息,我们可以称其为:中断信息。

中断信息可以来自CPU内部和外部

这一章中,我们主要讨论来自于CPU内部的中断信息

12.1内中断的产生

中断类型码为一个字节型数据,可以表示256种中断信息的来源。

当CPU内部有下面的情况发生的时候,将产生相应的中断信息。

1:除法错误,比如,执行div指令产生的除法溢出

2:单步执行

3:执行into指令

4:执行int 指令

8086CPU用称为中断类型码的数据来标识中断信息的来源。

上述的4种中断源,在8086CPU中的中断类型码如下:

1.除法错误:0

2.单步执行:1

3.执行into指令:4

4.执行int指令,该指令的格式为int n,指令中的n为字节型立即数,是提供给CPU的中断类型码。

12.2中断处理程序

CPU收到中断信息后,需要对中断信息进行处理。而如何对中断信息进行处理,可以由我们编程决定。一般来说,需要对不同的中断信息编写不同的处理程序。

可见首要的问题是,CPU在收到中断信息后,如何根据中断信息确定其处理程序的入口。

CPU的设计者必须在中断信息和其处理程序的入口地址之间建立某种联系,使得CPU根据中断信息可以找到要执行的处理程序。

根据CPU的设计,中断类型码的作用就是用来定位中断处理程序。

可随之而来的问题是,若要定位中断处理程序,需要知道它的段地址和偏移地址,而如何根据8位的终端类型码得到中断处理程序的段地址和偏移地址呢?

12.3中断向量表

CPU用8位的中断类型码通过中断向量表找到相应的中断处理程序的入口地址。那么什么是中断向量呢?就是中断处理程序的入口地址。

中断向量表在内存中保存,其中存放着256个中断源所对应的中断处理程序的入口。

在这个方案中,一个首要的问题是,CPU如何找到中断向量表?现在,找到中断向量表成了通过中断类型码找到中断处理程序入口地址的先决条件。

中断向量表在内存中存放,对于8086PC机,中断向量表指定放在内存地址0处。从0000:0000到0000:03FF的1024个单元中存放着中断向量表。

那么在中断向量表中,一个表项占多大的空间呢?一个表项存放一个中断向量,也就是一个中断处理程序的入口地址,对于8086CPU,这个入口地址包括段地址和偏移地址,所以一个表项占两个字,高地址字存放段地址,低地址字存放偏移地址。

存储N号中断源对应的中断处理程序入口的偏移地址的内存单元的地址为4N

存储N号中断源对应的中断处理程序入口的段地址的内存单元的地址为4N+2

12.4中断过程

找到这个入口地址的最终目的是用它设置CS和IP,使CPU执行中断处理程序。

用中断类型码找到中断向量,并用它设置CS和IP,这个工作是由CPU的硬件自动完成的。

CPU硬件完成这个工作的过程称为中断过程。

CPU收到中断信息后,要对中断信息进行处理,首先将引发中断程序。硬件在完成终端过程后,CS:IP将指向中断处理程序的入口,CPU开始执行中断处理程序。

在中断过程中,在设置CS:IP之前,还要将原来的CS和IP的值保存起来。在使用call指令调用子程序时有同样的问题,子程序执行后还要返回到原来的执行点继续执行,所以,call指令先保存当前CS和IP的值,然后再设置CS和IP。

下面是8086CPU在收到中断信息后,所引发的中断过程。

1.(从中断信息中)取得中断类型码

2.标志寄存器的值入栈(因为在中断过程中要改变标志寄存器的值,所以先将其保存在栈中)

3.设置标志寄存器的第8为TF和第9位IF的值为0(这一步的目的后面将介绍)

4.CS的内容入栈

5.IP的内容入栈

6.从内存地址为中断类型码*4和中断类型码*4+2的两个字单元中读取中断处理程序的入口地址设置IP和CS。

 可以看到CPU将它们保存在栈中。我们注意到,在中断过程中还要做的一个工作就是设置标志寄存器的TF,IF位,对于这样做的目的,将在后面的内容中介绍。

因为在执行完中断处理程序后,需要恢复在进入中断处理程序之前的CPU现场(某一时刻,CPU中各个寄存器的值)。所以应该在修改标识寄存器之前,将它的值入栈保存。

我们更简洁地描述中断过程,如下:

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中断处理程序和ire指令

由于CPU随时都可能检测到中断信息,也就是说,CPU随时都可能执行中断处理程序,所以中断处理程序必须一直存储在内存某段空间之中。

中断处理程序的编写方法和子程序的比较相似,下面是常规的步骤:

1.保存用到的寄存器

2.处理中断

3.恢复用到的寄存器

4.用iret指令返回。

iret指令的功能用汇编语法描述为:

pop IP

pop CS

popf

iret指令执行后,CPU回到执行中断处理程序前的执行点继续执行程序。

12.6除法错误中断的处理

12.7编程处理0号中断

我们将自己编写的程序称为do0。

现在的问题是:do0应该放在哪里呢?

由于我们是在操作系统之上使用计算机,所有的硬件资源都在操作系统的管理之下,所以我们想要得到一块内存区存放do0,应该向操作系统申请。

但在这里出于两个原因我们不想这样做:

1.过多地讨论申请内存将偏离问题的主线

2.我们学习汇编的一个重要目的就是要获得对计算机底层的编程体验。所以,在可能的情况下,我们不去理会操作系统,而直接面向硬件资源。

问题变得简单而直接,我们只需找到一块别的程序不会用到的内存区。

前面讲到,内存0000:0000-0000:03FF,大小为1KB的空间是系统存放中断处理程序入口地址的中断向量表。但是,实际上,系统要处理的中断事件远没有达到256个。

一般情况下,从0000:0200-0000:02FF的256个字节的空间所对应的中断向量表都是空的。

结论:我们可以将do0传送到内存0000:0200处。

12.8 安装

12.9 do0

12.10 设置中断向量

12.11 单步中断

我们来简要地考虑一下Debug是如何利用CPU所提供的单步中断的功能的。

首先,Debug提供了单步中断的中断处理程序,功能为显示所有寄存器中的内容后等待输入命令。然后,在使用t命令执行指令时,Debug将TF设置为1,使得CPU工作于单步中断方式下。

在进入中断处理程序之前,设置TF=0。从而避免CPU在执行中断处理程序时发生单步中断。

这也就是为什么在中断过程中有TF=0这个步骤。

(这个问题要再仔细考虑考虑)

12.12 响应中断的特殊情况

在有些情况下,CPU在执行完当前指令后,即便是发生中断,也不会响应。例如:在执行完向ss寄存器传送数据的指令后,即便是发生中断,CPU也不会响应。

我们应该利用这个特性,将设置ss和sp的指令连续存放,使得设置sp的指令紧接着设置ss的指令执行,而在此之间,CPU不会引发中断过程。

实验12 编写0号中断的处理程序

猜你喜欢

转载自www.cnblogs.com/JasonPeng1/p/12110079.html