内中断
一般cpu都有一种能力,就是接受cpu内部或外部发来的信号,停止当前程序而取执行其他的程序。这种信息叫做中断信息,中断信息指的是cpu接受到这种信息后立刻处理这个信息。接受到这个信息后cpu会交给专门的程序去处理,叫做中断处理程序
内中断
内中断指的是中断信息来自cpu内部。当cpu接受到相应几种情况时,会产生相应的中断信息
- 除法错误 例如 ,div除法溢出
- 单步执行
- 执行into指令
- 执行int 指令
我们先不需要了解具体含义。为了更方便的知道到底属于那种中断信息,8086cpu用了一个字节的中断类型码来确定。
- 除法错误 0
- 单步执行 1
- 执行into指令 4
- int: int n ,n就是中断类型码
cpu根据cs:ip知道程序的入口,所以中断类型码中必定有cs:ip的信息,可cpu如何根据8位的类型吗知道程序的入口呢?
中断向量表
cpu通过中断类型码找到中断向量表,而中断向量表中就保存着程序的入口。中断向量表在内存中保存。中断内存表位于0000:0000 到 0000:03ff 1024个字节中
中断过程
找到cs:ip的过程叫做中断过程。
cpu收到中断信息后,要对中断信息进行处理。但是完成中断程序之后还要返回,就像call和ret一样。所以总过程如下
- 获得中断类型码
- 标志寄存器的值入栈(因为中断过程会改变标志寄存器的值)
- 设置标志寄存器第8位和第九位的值为0
- cs入栈
- ip入栈
- 设置cs:ip
更简洁的说明
- 获得 中断类型码 n
- pushf
- tf=0 if=0
- push cs
- push ip
- ip=n4,cs=n4+2
iret指令
中断处理程序用iret进行返回
内容
pop ip |
这个正好与进栈顺序相反
除法错误中断的处理
cpu如果产生除法溢出错误,将会产生中断类型码为0的中断信息。引发中断过程。然后中断处理程序会返回 divide overflow 再返回到主程序中
过程
cs:code |
注意:do0也要返回
安装
用movsb指令,将do0的代码送入0:200处cs:code
code
start: 设置es:di指向目的地址
设置ds:si指向源地址
设置传输长度
设置传输方向为正
rep movsb
设置中断表
...
我们如何知道do0代码长度?
可以用编译器来知道do0的长度
mov cx,offset do0end-offset do0
“-”是编译器识别的符号,编译器可以用它来做两个常数的减法
例如 mov ax,(5+3)*5/10 被编译器识别为 mov ax,4
do0
do0的主要任务是显示字符串do0: 设置ds:si指向字符串
mov ax,0b800h
mov es,ax
mov di,12*160+36*2
mov cx,9
s: mov al,[si]
mov es:[di],al
inc si
add di,2
loop s
mov ax,4c00h
int 21h
do0end:nop
这个程序看起来对,实际上有问题,因为程序执行完后内存立刻被释放,其中保存的内容也可能被其他的程序覆盖。正确的程序如下
... |
设置中断向量
现在do0的入口为 0:200 ,写入中断向量表的0号表项中。使do0成为0号中断处理程序
0号表项地址为0:0 ,其中0:0存放偏移地址,0:2存放段地址。程序如下mov ax,0
mov es,ax
mov word ptr es:[0*4],200h
mov word ptr es:[0*4+2],0
单步中断
cpu执行完一条指令后,如果检测到tf=1,则产生单步中断,单步中断类型码为1,过程如下
- 获得中断类型码
- 标志寄存器入栈,tf if设置为0
- cs,ip入栈
- ip=14 cs=14+2
cpu为什么要提供单步中断呢?在debug的t命令中,为什么执行完一条 指令后,能够实时的反映寄存器的状态?这便是cpu单步中断导致可以一条条指令执行