汇编语言(王爽)第十二章 内中断

第十二章

CPU可以在执行完当前正在执行的指令之后,检测到从CPU外部或内部产生的一种特殊信息,并且可以立即对所接收到的信息进行处理,这种特殊的信息称为中断信息,其向所要进行的该种处理提供了必备的参数的通知信息

中断:CPU不在接着刚执行完的指令向下执行,而是转去执行这个特殊信息

12.1 内中断的产生

对于8086CPU,当CPU内部有下面的情况发生的时候,将产生中断信息

1、除法错误,比如,执行div指令产生的除法溢出

2、单步执行

3、执行into指令

4、执行int指令

CPU首先要知道,所接受到的中断信息的来源,所以中断信息中必须包含识别来源的编码,称为中断类型码,为一个字节型数据,可以表示256种中断信息的来源,我们将产生中断信息的事件,即中断信息的来源,简称为中断源

上述4种中断源的中断类型码如下

1、除法错误:0

2、单步执行:1

3、执行into指令:4

4、执行int指令,该指令的格式为int n,指令中的n为字节型立即数,是提供给CPU的中断类型码

12.2 中断处理程序

如何对中断信息进行处理,可以由我们编程决定,用来处理中断信息的程序被称为中断处理程序,不同的中断信息编写不同的处理程序

CPU收到中断信息后,应该转去执行相应的中断处理程序,即设置CS:IP指向该程序的入口,所以需要在中断信息和其处理程序的入口地址之间建立某种联系

中断信息中包含有标识中断源的类型码,中断类型码的作用就是定位中断处理程序,那么如何根据8位中断类型码得到中断处理程序的段地址和偏移地址?

12.3 中断向量表

CPU用8位的中断类型码,通过查找中断向量表找到相应中断处理程序的入口地址

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

中断向量表在内存中保存,其中存放着256个中断源所对应的中断处理程序的入口,在8086PC机中,中断向量表指定放在内存地址0处,从0000:0000到0000:03FF共1024个单元

中断向量表中一个表项存放一个入口地址,占两个字,高地址字存放段地址,低地址字存放偏移地址

中断向量表(内存中)
0号中断源对应的中断处理程序的入口地址
1号中断源对应的中断处理程序的入口地址
2号中断源对应的中断处理程序的入口地址
3号中断源对应的中断处理程序的入口地址
……

用Debug查看内存,情况如下:

0000:0000 68 10 A7 00 8B 01 70 00-16 00 9D 03 8B 01 70 00

则3号中断源对应的中断处理程序的入口地址为:0070:018B

12.4 中断过程

用中断类型码找到中断向量,并用它设置CS和IP,这个工作由CPU的硬件自动完成。这个过程称为中断过程,硬件完成中断过程后,CPU开始执行CS:IP指向的中断处理程序

CPU在指向玩中断处理程序后,还要返回原来的执行点继续执行下面的指令,所以在中断过程中,设置CS:IP之前,要将原来的CS和IP保存起来(CPU在取完一条指令后,执行这条指令前,IP指向下一条指令)

具体过程:

1、(从中断信息中)取得中断类型码

2、标志寄存器的值入栈(中断过程要改变标志寄存器的值) pushf

3、设置标志寄存器的第8位TF和第9位IF的值为0

4、CS的内容入栈 push CS

5、IP的内容入栈 push IP

6、从内存中读取中断处理程序的入口地址

最后一步完成后,CPU开始执行由程序员编写的中断处理程序

12.5 中断处理程序和iret指令

CPU随时都可能检测到中断信息,也就是说。CPU随时都可能执行中断处理程序,所以中断处理程序必须一直存储在内存某段空间之中(CPU可以直接访问内存)

中断处理程序的编写方法和子程序的比较相似

1、保存用到的寄存器

2、处理中断

3、恢复用到的寄存器

4、用iret指令返回 pop IP pop CS popf

iret通常和中断过程配合使用

12.6 除法错误中断的处理

当CPU执行div等除法指令时,如果发生了除法溢出错误,将产生中断类型码为0的中断信息,引发中断过程,执行相应中断处理程序

mov ax,1000h
mov bh,1
div bh

该中断处理程序会显示提示信息"Divide overflow",返回到操作系统中

12.7 编程处理0号中断

重新编写一个0号中断处理程序,当除法溢出时,在屏幕中间显示"overflow",返回DOS

这里我们跳过操作系统,直接面向硬件

在内存储存中断向量表的空间中,有很多单元(0000:0200至0000:02FF)是空的,可以存放我们的程序

同时,在中断向量表对应的表项中设置新的地址

程序框架为

assume cs:code

code segment

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

该程序执行时do0部分是不执行的,而是作为中断处理程序被复制到内存0:0200处,最后两行代码是根据要求返回DOS

do0部分的代码只有在被复制到0:200处,且设置中断向量表完毕后,才成为0号中断的中断处理程序

即:让一段程序成为N号中断的中断处理程序,需要将它的入口地址放入中断向量表的N号表项中

12.8 安装

可以使用movsb指令,将do0的代码送入0:200处,因此我们需要知道原始位置和目的位置,以及do0代码的长度,我们利用编译器来计算do0的长度,具体做法见代码

assume cs:code

code segment

	start:	mov ax,cs
			mov ds,ax
			mov si,offset do0		; 设置ds:si指向源地址
			
			mov ax,0
			mov es,ax
			mov di,200h				; 设置es:di指向目的地址
			
			mov cx,offset do0end-offset do0
			
			cld						; 设置正向传输
			rep movsb
			
			设置中断向量表
			
			mov ax,4c00h
			int 21h
			
	  do0:	显示字符串"overflow!"
	  		mov ax,4c00h
	  		int 21h
	  		
   do0end:	nop
	  		
code ends
end start

"-"是编译器识别的运算符号,可以用来进行两个常数的减法

mov ax,8-4			; 编译器处理为mov ax,4
mov ax,(5+3)*5/10	; 编译器处理为mov ax,4

12.9 do0

字符串"overflow"的位置值得思考,如果跟之前一样,在主程序中开辟一个data段,那么在程序执行结束后,其占用的内存空间被系统释放,data段的位置可能会被别的信息覆盖,到时候可能显示的就不是正确的内容

所以应该把字符串放在一段不会被覆盖的空间中

assume cs:code

code segment

	start:	mov ax,cs
			mov ds,ax
			mov si,offset do0		; 设置ds:si指向源地址
			
			mov ax,0
			mov es,ax
			mov di,200h				; 设置es:di指向目的地址
			
			mov cx,offset do0end-offset do0
			
			cld						; 设置正向传输
			rep movsb
			
			设置中断向量表
			
			mov ax,4c00h
			int 21h
			
	  do0:	jmp short do0start
	  		db "overflow!"		; 使用一部分内存存储字符串
	  		
 do0start:	mov ax,cs
 			mov ds,ax
 			mov si,202h			; 设置ds:si指向字符串
 			
 			mov ax,0b800h
 			mov es,ax
 			mov di,12*160+36*2	; 设置es:di指向显存空间的中间位置
 			
 			mov cx,9
 		s:	mov al,[si]
 			mov es:[di],al
 			inc si
 			add di,2			; 注意每个字符之后为该字符的信息,所以di每次加2 
 			loop s
 			
	  		mov ax,4c00h
	  		int 21h
	  		
   do0end:	nop
	  		
code ends
end start

当除法溢出发生时,CPU执行0:200处的jmp指令跳过字符串,转到正式的程序执行

该字符串的段地址与溢出发生时执行的中断处理程序段地址相同,由于jmp short do0start占两个字节,所以偏移地址为202h

12.10 设置中断向量

将do0的入口地址写入0号表项中

mov ax,0
mov es,ax
mov word ptr es:[0*4],200h
mov word ptr es:[0*4+2],0

12.11 单步中断

CPU在执行完一条指令后,若检测到标志寄存器的TF位为1,则产生单步中断,中断类型码为1

中断过程如下:

1、取得中断类型码1

2、标志寄存器入栈,TF、IF设置为0

3、CS、IP入栈

4、设置CS、IP

如Debug的T命令,可以单步执行被加载程序的指令

Debug提供了单步中断的中断处理程序,功能为显示所有寄存器中的内容后等待输入,然后在使用t命令时,Debug将TF设置为1,使得CPU工作于单步中断方式下,则在CPU执行完这条指令后就引发单步中断,执行单步中断的中断处理程序,在屏幕上显示寄存器的内容,并等待输入命令

中断处理程序也是由一条条指令组成的,如果执行中断处理程序之前TF仍为1,则在执行完中断处理程序的第一条指令以后,又会产生单步中断……不断套娃,所以我们注意到在中断过程中,TF被设置为0

所以完整过程为:T命令(设置TF=1)->执行当前指令->中断过程(设置TF=0)->中断处理程序执行(显示寄存器内容&等待输入)->T命令(设置TF=1)->返回程序执行下一条指令……

CPU提供单步中断功能的原因是,为单步跟踪程序的执行过程提供了实现机制

12.12 响应中断的特殊情况

在有些情况下,CPU在执行完一条指令后,即便发生中断,也不会立即响应

举例:在执行完mov ss,ax之后,即便发生中断,也不会响应,因为这样可能会导致ss:sp联合指向栈顶时,指向不正确的栈顶,导致错误,所以CPU在执行完设置ss的指令后,不响应中断,这给连续设置ss和sp提供了机会,所以我们应该利用这一特性,将两条指令连续存放,如果将栈顶设置为1000:0,不应该

mov ax,1000h
mov ss,ax
mov ax,0
mov sp,0

因此,在Debug利用单步中断实现T命令时,在mov ss,ax指令执行之后,CPU不响应中断(不管下一条是什么指令,都不响应),而是等到下一条指令mov sp,10h执行后,才响应中断

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值