1.中断的基本概念
中断是指在计算机执行期间,CPU收到某个信号(来自软件或硬件),暂时保存正在执行的程序的上下文,转而去执行相应的中断处理程序.
2.8086CPU内部有内部有下面的情况发生时,将产生相应的中断信息.
- 除法错误,比如div指令产生的除法溢出 中断码:0
- 单步执行; 中断码: 1
- 执行into指令 中断码:4
执行int指令 中断码:n
cpu收到中断信息后,就会对中断信息进行处理,而如何处理,可以由我们编程决定,我们编写的用来处理终端信息的程序就被称为中断处理程序,一般来说,对不同的中断信息,就要编写不同的处理程序.
我们知道,要想让8086CPU执行某处的程序,就要将CS:IP指向它的入口地址.那么,产生中断后,怎么定位中断处理程序的入口地址呢?
3.中断向量表
CPU用8位的中断码通过中断向量表找到相应的中断处理程序的入口地址,简单的来说,就是一个中断码和中断处理程序入口地址的映射表:
中断码 | 中断处理程序的入口地址 |
---|---|
0 | 0号中断处理程序的地址 |
1 | 1号中断处理程序的地址 |
… | ….. |
中断向量表在内存中存放,内存0000:0000到0000:03FF的1024个单元中存放中断向量表.(8086规定).对于8086一个表项占32位,低16位表示的是偏移地址,高16位表示段地址.
比如说,产生中断3,8086就会在上图的内存区域的0000:0009~0000:000A处取得3号中断处理程序的偏移地址是0008,000A:000B处取段地址为0070,计算的得到中断程序的入口地址为0070:0008=00708H,CPU就会去执行00708处的指令,当然,我们要编写自己的中断处理程序,就需要把自己的中断处理程序放在内存的某个地方,然后修改中断向量表,当发生相应的中断时,就会执行用户自己的中断处理程序;
中断处理程序存在哪片内存空间
前面讲到内存0000:0000-0000:03FF,大小为1kB的空间是8086系统用来存放中断向量表的地方,8086支持256个中断,但是,实际上,系统中要处理的中断远没有256个,所以,在中断向量表中,很多单元是空的。
中断向量表是PC系统中最重要的内存区,只用来存放中断处理程序的入口地址,DOS系统和其它应用不会使用,因此,我们可以用其空闲的内存区域存放我们的程序,一般从0000:0200至0000:02FF这256个字节是空的,操作系统和应用都不会占用.
例子:
0号中断处理程序:
assume cs:code
code segment
start:
mov ax,cs
mov ds,ax ;源程序的段地址,
mov si,offset do0 ;将中断处理程序的入口的偏移地址存在si中
mov ax,0
mov es,ax ;目的位置的段地址放在es中
mov di,200h ;目的位置的偏移地址0000:0200处
mov cx,offset do0end-offset do0 ;计算要把多少个字节拷贝.
cld ; 将df置为0,
rep movsb ;rep movsb 指定把代码段do0-do0end这段代码拷贝到0000:0200-0000:0200+(do0end-do0)
mov word ptr es:[0*4],200h ;修改偏移地址
mov word ptr es:[0*4+2],0 ;段地址
mov ax,4c00h
int 21h
do0:
jmp short do0start ;占两个字节
db "divide error!"
do0start:
mov ax,cs;中断后cs=0,ip=200h
mov ds,ax
mov si,202h ; 指向db的首地址
mov ax,0b800h
mov es,ax
mov di,12*160+33*2
mov cx,13
s:
mov al,[si]
mov es:[di],al
mov byte ptr es:[di+1],2h
inc si
add di,2
loop s
mov ax,4c00h
int 21h
do0end:nop
code ends
end start
导致中断函数:
assume cs:code
code segment
start:
mov ax,1000h
mov bh,1
div bh ;产生0号中断
code ends
end start
在dosbox中先执行中断处理程序,相当于把中断处理函数放到内存中,并更新中断向量表.
中断触发函数
assume cs:code
code segment
start:
mov ax,1000h
mov bh,1
div bh
code ends
end start
执行此程序会触发0号中断,执行上面的do0-do0end之间的程序,在终端中间显示”divide error!”;
执行结果如下: