【笔记】8086汇编-内中断

前言:本篇仅仅是笔记,整理于2017/9/4,结构可能会略有混乱,见谅。

-中断可能来自于计算机内部和外部,我们这里只讨论内中断。

-内中断是不可以屏蔽的,因为内中段常常反映了异常工作。

-【12.1  内中断的产生】

–对于8086CPU,当CPU内部有以下情况发生时,会产生中断信息:

—1)除法错误,比如:执行div指令产生的除法溢出;【中断类型码:0】

—2)单步执行;【中断类型码:1】

—3)执行into指令;【中断类型码:4】

—4)执行int指令。【int n,其中的n为字节型立即数,是提供给CPU的中断类型码】

–8086CPU使用中断类型码来标识中断信息的来源。中断类型码是一个字节型数据,可以表示256种中断信息的来源。【为了方便,以后,我们将中断信息的来源,简称为中断源】

-【12.2/3  中断处理程序、中断向量表】

–我们知道,中断后CPU要执行一定的程序来处理这一中断信息,这种程序我们称为中断处理程序。

–我们需要用8位中断类型码来定位对应的中断处理程序,我们创造并使用中断向量表来建立这种对应关系。

–所谓中断向量,就是中断处理程序的入口地址。

–中断向量表就是中断处理程序入口地址的列表。

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

–8086CPU,内存0000:0000~0000:03FF的1024个单元中存放着中断向量表,中断向量表固定放在这里,一个表占4个字节(1024/256),高地址字存放段地址,低地址字存放偏移地址。

–存储N号中断源对应的中断处理程序入口的偏移地址的内存单元(也就是入口地址的位置)为:4N

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

-【12.4  中断过程】

–中断过程是由CPU的硬件自动完成的,这个过程是:用中断码找到中断向量,并用它设置CS和IP。

–另外,在执行完中断程序后,应当回到原来的位置继续向下执行,所以在设置CS、IP前,应当将原来的CS、IP储存起来。

–中断过程:

—取得中断类型码→标志寄存器的值入栈(因为中断过程中要改变标志寄存器的值)→设置标志寄存器的TF(8位)、IF(9位)的值为0→CS入栈→IP入栈→从对应位置读取IP与CS。

-【12.5  中断处理程序和iret指令】

–中断处理程序与中断向量表是需要时刻存储在内存空间中的,因为CPU随时都可能执行中断处理程序。

–关于中断处理程序的编写,主要有以下四块:1)保存用到的寄存器;2)处理中断;3)恢复用到的寄存器;4)使用iret指令返回【iret相当于:pop IP→pop CS→popf】。可以看出,这个框架与子程序的编写框架十分类似。

-【12.6  除法错误中断处理】

–我们试验如下程序:

–mov ax,1000h

–mov bh,1

–div bh

-执行完第三行后,显示提示信息:”Divide overflow”

-【12.7  编程处理0号中断】

–我们只要将中断向量表中的数据设置为指向中断处理程序就可以了。

–我们在这里不想通过向操作来申请空间,所以我们要将中断处理指令复制到一个固定的位置(下面简称:安装),我们前面讲的安全的空间就可以满足需求(0:200~0:2FF),由于没有那么多的中断向量,这段空间便被空了出来。

-【12.8  安装】

–我们使用rep movsb来进行安装,es:di指向目的地址,ds:si指向原始地址,cx设定传送长度。

–之后再设定中断向量表。

–这里有个关键问题:如何知道要传送的长度?

—我们的解决方法是,将起始位置设置一个标号a,然后将结束的位置后加一行nop指令,并将另一个标号b设置在这里,我们使用mov cx,offset b – offset a就可以知道要复制的长度了。【编译器能够进行四则运算(加减乘除),可以直接用运算符号来表示】

–我们还要注意:要输出的字符不可以放在一个单独的段中,因为一个段中的空间,在程序结束时会被回收,我们需要将要显示的字符串也放到刚才我们找到的安全空间,所以我们可以在要复制的程序的开头加上jmp指令,下一行加上db来定义字符串,而前面的jmp用来跳过这个字符串定义过程。

–【个人想到:如果代码段的开头加上jmp,然后下一行定义的是一系列数据,而jmp来跳过这些数据,这样在实际运行时,就无法通过开头来知晓所有的指令了,以此起到伪装作用】

–【注意:jmp short指令只占两个字节】

-【12.10  设置中断向量】

–这步十分简单,只要将IP、CS以字型数据存放到对应的位置即可。

-【12.11  单步中断】

–产生方式:CPU执行完一条指令后,如果检测到标志寄存器的TF位为1,则产生单步中断。【或者说,当TF变成1,再执行一条指令后,进入单步中断】

–单步中断的中断类型码是1,CPU取得中断类型码1后,会进行中断过程(包括一系列的入栈、TF, IF归零、CS, IP重指向)。

–实际上,当我们在debug中使用t命令时,Debug就会将TF设置为1,执行一条语句(TF=1时执行一条语句就会引发单步中断),自然引发单步中断,之后所有寄存器中的内容被显示在屏幕上,等待输入指令。

–为了避免单步中断进入死循环,当进入单步中断时,TF会自动变成0.

-【12.12  响应中断的特殊情况】

–有些情况,当CPU执行完当前指令,即便发生中断,也不会响应。我们这里仅举一例。

—我们之前就遇到过,当执行mov ss,ax之后,下一条mov sp,16并不会在debug中显示,这是因为,在执行完向ss寄存器传送数据的指令后,即便发生中断,CPU也不会响应,这是为了防止因为栈还未配置好,就进行中断过程的入栈操作【如果这样,必然会引发错误】。不过这种机制只有在改变ss的指令后紧跟着改变sp的指令时才会触发,所以我们的设计应当将修改sp的指令放在修改ss的指令紧下方。