汇编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