汇编13:int指令

int指令

int指令也可以引发内中断。

int指令的格式是:

int n

其中n为中断类型码。

相当于执行以下步骤:

1、取到中断类型码n

2、标志寄存器入栈,IF=0,TF=0

3、CS、IP入栈

4、根据中断向量表修改CS和IP:(IP)=(n*4),(CS)=(n*4+2)

可见int指令的最终功能就是执行一段中断处理程序。

案例:以中断程序的方式实现计算式

需求:求一word型数据的平方,求2*(3456的平方),dx、ax中存放结果的高16位和低16位。

首先准备安装程序:

assume cs:code
code segment
start:	mov ax,cs
	mov ds,ax
	mov si,offset sqr						设置ds:si指向源地址
	mov ax,0
	mov es,ax
	mov di,200h							设置es:di指向目的地址
	mov cx,offset sqrend-offset sqr			                设置传输长度
	cld								设置传输长度为正
	rep movsb							开始安装中断程序
		
	mov ax,0						        设置中断向量表
	mov es,ax
	mov word ptr es:[7ch*4],200h
	mov word ptr es:[7ch*4+2],0
		
	mov ax,4c00h
	int 21h
		
sqr:	mul ax								中断处理程序:将一个数求平方
	iret
		
sqrend:	nop

code ends
end start

然后产生对应中断完成功能:

assume cs:code
code segment
start:	mov ax,3456
	int 7ch									调用中断处理程序,完成平方
	add ax,ax								低16位相加
	adc dx,dx								高16位相加
	mov ax,4c00h
	int 21h
code ends
end start

案例:以中断程序的方式完成loop指令循环

需求:在屏幕中间显示80个“!”

程序:

assume cs:code
code segment
start:	mov ax,0b800h
	mov es,ax
	mov di,160*12
		
	mov bx,offset s-offset se				        计算从se到e的转移位移
	mov cx,80							设置循环次数
s:	mov byte ptr es:[di],'!'				        在屏幕上显示符号
	add di,2
	int 7ch								用这条指令代替loop s
se:	nop
	mov ax,4c00h
	int 21h
code ends
end start

要想用int 7ch代替loop s,必须使其完成两项内容:cx的自减以及将执行跳转到s标号处。

要跳转到s标号处,必须设置cs和ip。当中断发生时,此时会把当时的cs和ip压入栈中,中断完成后取出恢复。我们要想办法让栈中取出的值对应的cs和ip就是标号s处。这里的cs是不用改变的,因为跳转发生在同一个段中,关键是ip要发生改变。

中断程序:

lp:	push bp
	mov bp,sp
	dec cx
	jcxz lpret
	add [bp+2],bx
lpret:	pop bp
	iret

下面我们重点研究这段代码,当中断发生时,int 7ch这句代码的cs和ip会入栈,然后把bp寄存器压入栈中,将sp寄存器赋值给bp(ss:sp时刻指向栈顶,sp相当于偏移地址),然后自减cx,如果cx不为0则继续执行:

[bp+2],bx

当bp寄存器在中括号中,默认的段地址在ss中,也就是说这条语句实际上是一条改变栈的语句,因为bp此时就等于sp,所以这条语句实际上改变的是栈顶往下第二个元素,也就是刚刚中断时压入栈中的ip,这个值加上bx就相当于再次指向标号s(bx是转移位移),然后bp弹栈,结束中断。如果cx为0,那么就直接跳到lpret执行,栈中的数据不改变,cs和ip的值也不变,相当于loop结束。

为什么一定要把bp放入栈中再取出呢?因为bp是一个中间寄存器,它的值在调用中断程序前后不能发生变化。

为什么没有关于标志寄存器的操作?因为它是第一个被放入栈中的,也就是栈底数据,和本例无关。

由此可见,根据中断时cs和ip入栈的性质,我们也可以手动调整栈来完成跳转。

BIOS和DOS提供的中断机制

在系统板的ROM中存放着一套程序,称为BIOS(基本输入输出系统),BIOS中主要包含以下几部分内容:

1、硬件系统的检测和初始化程序

2、外部中断和内部中断的中断例程

3、用于对硬件设备进行的IO操作的中断例程

4、其他和硬件系统相关的中断例程

操作系统DOS也提供了很多中断例程,从操作系统的角度来看,DOS的中断机制就是操作系统向程序员提供的编程资源。

程序员在编程的时候可以用int指令直接调用BIOS和DOS提供的中断例程来完成对应的功能。

它们的执行过程如下:

1、开机后CPU初始化CS=0FFFFH,IP=0,开始执行程序,这个位置有一个跳转指令,CPU转去执行BIOS中的硬件系统检测和初始化程序。

2、初始化程序将BIOS提供的中断程序的入口地址登记在中断向量表中。

3、硬件系统检测和初始化完成后,调用int 19h进行操作系统的引导,将计算机交给操作系统来控制。

4、DOS启动后,将其中断程序装入内存并更新中断向量表。

BIOS中断例程应用

int 10h是BIOS提供的一个中断例程,其中包含了多个和屏幕输出相关的子程序。

设置光标位置功能:

mov ah,2							调用中断程序的2号子程序,设置光标位置
mov bh,0							位置在第0页,一般就是屏幕中
mov dh,5							行号为5
mov dl,12							列号为12
int 10h								

在光标位置显示字符:

mov ah,9							调用中断程序的9号子程序,在光标位置显示字符
mov al,'a'							字符为a
mov bl,7							颜色属性为7
mov bh,0							位置在第0页
mov cx,3							字符重复个数为3
int 10h

DOS中断例程应用

int21h是DOS提供的中断例程。

我们在前面一直在利用int 21h中断例程的4ch号功能完成程序返回功能:

mov ah,4ch							程序返回
mov al,0							返回值为0
int 21h

简写为:

mov ax,4c00h
int 21h

该中断例程也可以在光标位置显示字符串:

assume cs:code

data segment
	db 'Welcome to masm','$'
data ends

code segment
	start:	mov ah,2					设置光标位置
		mov bh,0
		mov dh,5
		mov dl,12
		int 10h
			
		mov ax,data					
		mov ds,ax
		mov dx,0					令ds:dx指向字符串,要显示的字符串必须是以$结尾
		mov ah,9					调用9号子程序,显示字符串
		int 21h
			
		mov ax,4c00h
		int 21h
code ends
end start

猜你喜欢

转载自www.cnblogs.com/yinyunmoyi/p/12811565.html