大灰狼笔记五之中断
一,中断概念
任何一个通用CPU都具备一种能力,可以在执行完成当亲正在执行的指令之后,检测到从CPU外部或内部产生的一种特殊信息,并立即对接受的信息进行处理。这种信息就是中断信息。(如开机Del后便进入BIOS设置)
中断是指,CPU不再接着(刚执行完的指令)向下执行,而是转而处理这个特殊信息。
二,中断向量表
CPU通过中断向量表找到需要执行的终端信息。
中断向量表在内存中保存,其中放着256个中断源所对应的中断处理程序的入口。
中断向量表一般都保存在内存0000:0000到0000:03FE。一个表项存放一个中断向量,即中断向量的入口地址,包括段地址和偏移地址,2个字。
遇到中断时,CPU将CS和IP中的内存地址入栈保存,等中断程序执行结束后通过出栈获得原来的CS,IP继续执行,这一过程都是CPU自动完成的。(这便是C中函数调用的本质)
中断向量表中的第一个中断向量是除法指令越界的除法错误中断。
div 寄存器 除数
其中除数可是8位和16位
被除数则默认放在ax或dx寄存器中,若除数为8位,则被除数默认为16位在ax寄存器中,若除数为16位,则被除数默认为32位在ax与dx寄存器中,其中dx存放高位,ax存放低位。
结果也是存储在这两个寄存器中,若除数为8位,则al存储除法的商,ah存余数;若除数为16位,则ax存储商,dx存储余数。
assume cs:code
code segment
start:
mov ax,1000h
mov bh,1
div bh
code ends
end start
执行代码后,出现的中断如下:
出现第一个除法中断。因此,我们想要修改中断向量表,即可修改中断向量表的入口地址
因此用一下两个语句可将第一个中断程序修改为我们希望运行的中断程序
mov ds:[0] 中断程序偏移地址
mov ds:[2] 中断程序基地址
三,中断执行程序
由于中断产生时必须马上执行,因此要保证中断程序不能被其他任何程序所覆盖,因此中断程序必须存放在任何程序都不能使用的空间中。
在中断向量表中,有一段表内空间系统一般不使用,而其他程序也没有办法使用,便可以用来存放我们想要执行的中断程序。
在中断向量表所在的内存中,0000:0200-0000:0300这一段系统没有进行使用。可以用来存储我们自己编写的中断程序。
于是这一段需要将0200赋给ds:[0],基地址0000赋给ds:[2]。
在编写中断程序时,由于程序都写在了中断向量表中,没有将代码段与数据段分开存放,而程序最开始是数据定义的指令,并不是代码执行的指令。我们写程序的目的是为了将字符在屏幕上显示,于是就需要使用jmp跳转指令使程序一进来就进行显示字符串的指令。
jmp指令分三种:
段间跳转:jmp far 标号 把CS:IP寄存器值变为标号所在的内存地址
段内跳转:jmp near 标号 只修改IP寄存器的偏移地址,不修改CS寄存器
段内短跳转:jmp short 标号 不修改CS和IP的值,编译器自动计算跳转位置
中断代码如下:
assume cs:code
code segment
start:
mov ax,0;中断向量表中0号表项内容进行修改,指向自己编写的中断入口地址
mov ds,ax
mov word ptr ds:[0],0200h;拷贝一个字
mov word ptr ds:[2],0
;把0号中断程序拷贝到中断向量表0号表项指向的内存地址
mov ax,cs
mov ds,ax
mov si,offset int0;into在的地址的偏移地址存入si
mov ax,0
mov es,ax
mov di,200h
mov cx,offset int0end-offset int0
cld
rep movsb;重复拷贝字节数,字节传送指令
;引发0号中断
mov ax,1000h
mov bh,1
div bh
mov ax,4c00h
int 21h
;编写中断程序,实现在屏幕中央显示字符串
int0:jmp short int0start
db "I'm r_drummer"
int0start:mov ax,0b800h
mov ax,0b800h
mov es,ax;配置显存首地址
;把字符串以此拷贝到显存空间中
mov ax,cs
mov ds,ax;把代码段放到数据段,中断未区分,同一个内容
mov si,202h;jump short占2字节
mov di,12*160+36*2;拷贝的目的地址,显示的地方
mov cx,13
s:mov al,ds:[si];最近的一段数据段中的内容即“I'm r_drummer”已经拷贝到ds:si所指向的内容
mov es:[di],al
inc si
add di,2
loop s
mov ax,4c00h
int 21h
int0end:nop
code ends
end start
程序执行的结果如下: