实验内容
编写0号中断处理程序,使得在除法溢出发生时,在屏幕中间显示字符串"divide error!",然后返回到DOS。
解题
这一章都在介绍中断,包括中断的产生、中断处理程序、中断向量表、中断过程、相关指令。
解决本次实验的前提是将本章的内容理解好,那么在完成这部分(原书第12章-内中断)之后,开始实验吧~
分析整个中断过程
(1)当发生除法溢出的时候,产生0号中断信息,从而引发中断。
CPU会完成以下工作:
- 取得中断类型码 0
- 标志寄存器入栈,TF、IF 设置为 0
- CS、IP入栈
- (IP) = (0 * 4), (CS) = (0 * 4 + 2)
对于第二步,为社么要将TF、IF设置为0?
在十一小节中王爽老师给出了解答:CPU在执行完一条指令之后,如果检测到标志寄存器TF位为1,则产生单步中断,引发中断过程。单步中断的中断类型码为1,它引发的中断过程如下:
这也是本问题的关键了,反过来想,如果TF不设置为0,很显然CPU在即将执行中断处理程序的第一条指令时检测到了TF为1,就会在执行完该条指令之后继续进入到单步中断的过程当中… 就这样可能无限循环下去了,所以在中断处理之前必须将TF置为0。
对于IF书中没有多余解释,对此笔者搜集到了以下资料:
↑Linux系统中的中断分类
只看表格中的第二行第一条的处理方式一栏:清除标志寄存器eflags的IF标志可屏蔽中断,笔者推测IF标志位的功能就是显示中断的开(On)关(Off),可以译为:Interrupt Flag,
(查阅了其他博客也确实是这样)
IF:中断允许标志位。它用来控制8086是否允许接收外部中断请求。若IF=1,8086能响应外部中断,反之则屏蔽外部中断;
这么想就能够串通了,只是用来屏蔽掉其他中断(处理中断的过程中关闭中断功能,确保能够顺利执行完本次中断,处理完成后再打开中断)
好了,现在明白CPU在发生中断之后做的事情了,那么我们需要完成什么呢?
1.相关处理
2.向显示缓冲区写入想要显示的字符串 “divide error!”
3.返回 DOS
按照王爽老师的讲解,将这段程序命名为 do0。
但是一个从未碰到过的问题来了:do0程序应该放到哪?
do0应该放到内存中,因为除法溢出随时可能发生,CPU随时都可能将CS:IP指向do0的入口,然后执行它。
按理来说我们需要向操作系统申请一块空间去放置do0程序,但是过多的讨论申请内存将偏离问题的主线,所以这里简单做:直接使用一块别的程序不会用到的内存区,将do0拷贝到其中就可以了。
在 12.3 中断向量表 章节中作者讲解了中断向量表的存储位置(针对8086CPU):
0