一般cpu都有一种能力,就是接受cpu内部或外部发来的信号,停止当前程序而取执行其他的程序。这种信息叫做中断信息,中断信息指的是cpu接受到这种信息后立刻处理这个信息。接受到这个信息后cpu会交给专门的程序去处理,叫做中断处理程序

内中断

内中断指的是中断信息来自cpu内部。当cpu接受到相应几种情况时,会产生相应的中断信息

  1. 除法错误 例如 ,div除法溢出
  2. 单步执行
  3. 执行into指令
  4. 执行int 指令

我们先不需要了解具体含义。为了更方便的知道到底属于那种中断信息,8086cpu用了一个字节的中断类型码来确定。

  1. 除法错误 0
  2. 单步执行 1
  3. 执行into指令 4
  4. int: int n ,n就是中断类型码

cpu根据cs:ip知道程序的入口,所以中断类型码中必定有cs:ip的信息,可cpu如何根据8位的类型吗知道程序的入口呢?

中断向量表

cpu通过中断类型码找到中断向量表,而中断向量表中就保存着程序的入口。中断向量表在内存中保存。中断内存表位于0000:0000 到 0000:03ff 1024个字节中

中断过程

找到cs:ip的过程叫做中断过程。

cpu收到中断信息后,要对中断信息进行处理。但是完成中断程序之后还要返回,就像call和ret一样。所以总过程如下

  1. 获得中断类型码
  2. 标志寄存器的值入栈(因为中断过程会改变标志寄存器的值)
  3. 设置标志寄存器第8位和第九位的值为0
  4. cs入栈
  5. ip入栈
  6. 设置cs:ip

更简洁的说明

  1. 获得 中断类型码 n
  2. pushf
  3. tf=0 if=0
  4. push cs
  5. push ip
  6. ip=n4,cs=n4+2

iret指令

中断处理程序用iret进行返回

内容

pop ip
pop cs
popf

这个正好与进栈顺序相反

除法错误中断的处理

cpu如果产生除法溢出错误,将会产生中断类型码为0的中断信息。引发中断过程。然后中断处理程序会返回 divide overflow 再返回到主程序中

过程

assume cs:code

code segment

start: do0安装程序
设置中断向量表
mov ax4c00h
int 21h
do0: 显示字符串“overflow!”
mov ax,4c00h
int 21h
code ends
end start

注意:do0也要返回

安装

用movsb指令,将do0的代码送入0:200处

assume cs:code

code segment
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: jmp short do0start
db "overflow!"
do0start: mov ax,cs
mov ds,ax
mov si,202h
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//用iret也可以,用的话表示还会返回主程序中
do0end: nop
code ends
end start

设置中断向量

现在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,过程如下

  1. 获得中断类型码
  2. 标志寄存器入栈,tf if设置为0
  3. cs,ip入栈
  4. ip=14 cs=14+2

cpu为什么要提供单步中断呢?在debug的t命令中,为什么执行完一条 指令后,能够实时的反映寄存器的状态?这便是cpu单步中断导致可以一条条指令执行