int指令是X86汇编语言中最重要的指令之一。它的作用是引发中断,调用“中断例程”(interrupt routine)。本文将介绍int指令的基本原理和应用,以及BIOS和DOS系统的中断例程。
一、int指令的原理
1,指令原型
int n
1)n 表示中断号,也可以称为中断类型码。n是一个字节大小的正整数,范围为“0 - 255”。
2)执行“int n”时,CPU从中断向量表中,找到第n号表项,修改CS和IP
(IP)=(n*4),(CS)=(n*4+2)
3)对8086PC,中断向量表指定放在内存地址0处(地址固定),共1024个字节。每个表项占两个字,低字存放偏移地址,高字存放段地址。
2,int指令执行过程
1)取中断类型码n;
2)标志寄存器入栈(pushf),IF=0,TF=0(重置中断标志位);
3)CS、IP入栈;
4)查中断向量表, (IP)=(n*4),(CS)=(n*4+2)。
3,中断例程的返回
中断例程既可以直接返回dos,如下
mov ax,4c00h
int 21h
中断例程也可以像子程序一样返回到中断产生的地方,这时,就需要用到“iret”——中断返回指令。
iret指令的汇编语法描述为:
pop IP
pop CS
popf
二、中断例程的应用
事实上,我们可以将中断例程(interrupt routine)当作子程序(函数)调用来实现一些特定功能。不同的是:
1)调用方式。中断例程通过“int n”引发中断,而被调用,通过“iret”返回;子函数通过“call label”指令调用,通过“ret”指令返回。
2)中断例程安装后,会长驻内存(除非退出DOS,或被覆盖),故中断例程可以被不同的程序反复调用;而子程序是随主程序一同被加载到一片连续的内存(逻辑上),只能在同一个程序内被调用。
为了演示中断例程的“功能特性”,书中用“int 7ch”例举三个不同功能的中断例程。
1)求一word型数据的平方;
2)将一个全是字母,以0结尾的字符串,转化为大写;
3)模拟loop指令。(修改栈内数据)
这三个功能性的程序,书中都有,且与下面的检测点13.1类似,我就不贴出来了。
检测点13.1
1)我们用7ch中断例程模拟loop指令,它能进行的最大转移位移是多少?
参考第八章,“转移指令的原理”,“jmp near ptr label”。
在模拟的过程中,使用bx保存和传递位移值。bx是16位的寄存器,故它的最大转移位移量为“(-32768,32767) ”。
2)用7ch中断例程完成jmp near ptr s指令的功能。
应用举例:在屏幕第12行,显示data段中的以0结尾的字符串
assume cs:code
data segment
db 'conversation',0
data ends
code segment
start:mov ax,data
mov ds,ax
mov si,0
mov ax,0b800h
mov es,ax
mov di,12*160
s:cmp byte ptr [si],0
je ok
mov al,[si]
mov ah,0cah
mov es:[di],ax
inc si
add di,2
mov bx,offset s - offset ok
int 7ch
ok:mov ax,4c00h
int 21h
code ends
end start
下面是中断例程:
assume cs:code
code segment
start:mov ax,cs
mov ds,ax
mov si,offset jump
mov ax,0
mov es,ax
mov di,200h
mov cx,offset jumpend - offset jump
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
jump:push bp
mov bp,sp
add [bp+2],bx
pop bp
iret
jumpend:nop
code ends
end start
三、BIOS提供的中断例程
BIOS,即“Basic Input Output System”,它是系统板的ROM(Read-Only Memory)中的一套程序。BIOS中的中断例程安装过程如下:
1)开机后,CPU一加电,初始化(CS)=0FFFFH,(IP)=0,(参考第一章可知,该地址位于系统板的ROM中),自动从FFFF:0单元开始执行程序。FFFF:0处有一条跳转指令,CPU执行该指令后,转去执行BIOS中的硬件系统检测和初始化程序。
2)初始化程序将建立BIOS所支持的中断向量,即将BIOS提供的中断例程的入口地址登记在中断向量表中。注意,对应BIOS所提供的中断例程,只需将入口地址登记在中断向量表中即可,因为它们是固化到ROM中的程序,一直在内存中存在(仅需登记,无需安装)。
3)硬件系统检测和初始化完成后,调用int 19h进行操作系统的引导。从此将计算机交由操作系统控制。
4)DOS启动后,除完成其他工作外,还将它提供的中断例程装入内存,并建立相应的中断向量。
关于BIOS的启动过程,可以参考:http://www.techbulo.com/760.html
检测点13.2
判断题
1)我们可以编程改变FFFF:0处的指令,使得CPU不去执行BIOS中的硬件系统检测和初始化程序。
False !
参考第一章,FFFF:0是系统板ROM中的地址,只能读,不能写。
2)int 19h中断例程,可以由DOS提供
False !
此时,操作系统还没有被引导加载。
四、BIOS和DOS提供的中断例程的子程序和参数
BIOS和DOS提供的中断例程,往往都包含几个子程序,一般通过设置“ah”的值来调用对应编号的子程序。此外,子程序还会用到其他的一些参数,都通过各个寄存器进行传递。
典型地,BIOS提供的“int 10h”中断例程,它就包含了“设置光标位置”和“显示字符”等功能子程序。DOS提供的中断例程,以“int 21h”为代表,它包括“函数返回”、“设置光标”和“显示字符”等等功能子程序。如下:
assume cs:code
data segment
db 'Welcome to masm','$'
data ends
code segment
start:mov ah,2 ; set cursor
mov bh,0 ; the zero page
mov dh,5 ; row number
mov dl,12 ; column number
int 10h
mov ax,data
mov ds,ax
mov dx,0
mov ah,9
int 21h
mov ax,4c00h
int 21h
code ends
end start
实验13
assume cs:code
code segment
s1: db 'Good,Better,Best,','$'
s2: db 'Never let it rest,','$'
s3: db 'Till good is better,','$'
s4: db 'And better,best.','$'
s : dw offset s1,offset s2, offset s3, offset s4
row: db 2,4,6,8
start:mov ax,cs
mov ds,ax
mov bx,offset s
mov si,offset row
mov cx,4
ok:mov bh,0 ; page number
mov dh,[si] ; row number
mov dl,0 ; column number
mov ah,2 ; set cursor
int 10h
mov dx,[bx] ; string addresss
mov ah,9 ; display string
int 21h
inc si
add bx,2
loop ok
mov ax,4c00h
int 21h
code ends
end start