第十三章
int指令引发的中断是另一种内中断
13.1 int指令
格式:int n,n为中断类型码
功能:引发中断过程
执行过程:
1、取中断类型码n
2、标志寄存器入栈,IF=0 TF=0
3、CS、IP入栈
4、(IP)=(n*4)
(CS)=(n*4+2)
从此转去执行n号中断的中断处理程序
assume cs:code
code segment
start: mov ax,0b800h
mov es,ax
mov byte ptr es:[12*160+40*2],'!'
int 0
code ends
end start
执行这段程序,屏幕中间显示一个!(我们编程所得),然后显示“Divide overflow”(这是int 0产生的中断引起的)
int指令的最终功能和call指令相似,都是调用一段程序
系统将一些具有一定功能的子程序以中断处理程序的方式提供给应用程序,我们可以通过int指令调用它们,也可以自己编写中断处理程序
我们将中断处理程序简称为中断例程
13.2 编写供应用程序调用的中断例程
编写、安装中断7ch的中断例程
功能:求一word型数据的平方
参数:(ax)=要计算的数据
返回值:dx、ax分别存放高16、低16位
例:求2*3456^2
assume cs:code
code segment
start: mov ax,3456
int 7ch
add ax,ax
adc dx,dx ; 上一条指令可能带有进位
mov ax,4c00h
int 21h
code ends
end start
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 ; pop IP pop CS popf
sqrend: nop
code ends
end start
中断例程与编写子程序时一样,要避免寄存器的冲突,要注意例程中用到的寄存器的值的保存和恢复
13.3 对int、iret和栈的深入理解
用7ch中断例程完成loop指令的功能
loop s指令的执行需要循环次数和到s的位移两个信息,7ch中断例程同样需要这两个信息,cx放储循环次数,bx存放位移
在屏幕中间显示80个‘!’
assume cs:code
code segment
start: mov ax,0b800h
mov es,ax
mov di,160*12
mov bx,offset s-offset se ; 转移位移
mov cx,80
s: mov byte ptr es:[di],'!'
add di,2
int 7ch
se: nop
mov ax,4c00h
int 21h
code ends
end start
转到标号应设置(CS)=标号s的段地址,(IP)=标号s的偏移地址
中断例程如何获得s的段地址和偏移地址:在中断过程中CS和IP都要入栈,(CS)即为s的段地址,(IP)为se的偏移地址,所以(IP)+(bx)即为s的偏移地址
如何设置CS:IP:可以利用iret,我们将(IP)+(bx)入栈,取代之前的(IP),用栈中的内容设置CS、IP,从而实现转移
7ch中断例程如下
lp: push bp ; 用到了bp,保存原来的值
mov bp,sp ; sp指向栈顶
dec cx
jcxz lpret
add [bp+2],bx ; [bp+2]存放原本IP值(即se的偏移地址)的字单元
lpret: pop bp
iret
7ch中断例程所能进行的最大转移位移是多少:FFFFH,s的偏移地址为0,int 7ch执行完毕后IP指向FFFFH
用7ch完成jmp near ptr s指令的功能,bx向中断例程传送转移位移
do0: push bp
mov bp,sp
add [bp+2],bx
pop bp
iret
13.4 BIOS和DOS所提供的中断例程
在系统板的ROM中存放着一套程序,称为BIOS(基本输入输出系统),BIOS中主要包含以下几部分内容
1、硬件系统的检测和初始化程序
2、外部中断和内部中断的中断例程
3、用于对硬件设备进行I/O操作的中断例程
4、其他和硬件系统相关的中断例程
操作系统DOS也提供了中断例程
BIOS和DOS所提供的中断例程中包含了许多子程序,可以用int指令直接调用
和硬件相关的DOS例程中一般都调用了BIOS的中断例程
13.5 BIOS和DOS中断例程的安装过程
开机后CPU加电,初始化(CS)=0FFFFH (IP)=0,自动从FFFF:0单元开始执行程序,FFFF:0处有一条跳转指令,CPU执行该指令后,转去执行BIOS中的硬件系统检测和初始化程序
初始化程序将建立BIOS所支持的中断向量,即将BIOS提供的中断例程的入口地址登记在中断向量表中,注意,对于BIOS所提供的中断例程只需要在中断向量表中登记入口即可,因为它们是固化在ROM中的,一直在内存中存在
硬件系统检测和初始化完成后,调用int19h进行操作系统的引导,从此将计算机交给操作系统控制
DOS启动后,除了完成其他工作,还将它所提供的中断例程装入内存,并建立相应的中断向量(操作系统并不存储在内存中,因此其中断例程是需要被加载到内存中的)
判断对错:
1、我们可以编程改变FFFF:0处的指令,使得CPU不去执行BIOS中的程序
错,因为ROM是只读的
2、int 19h中断例程可以由DOS提供
错,在调用int 19h之前,DOS还没启动
13.6 BIOS中断例程应用
int 10h中断例程由BIOS提供,其中包含多个和屏幕输出相关的子程序
一般来说,一个供程序员调用的中断例程往往包含多个子程序,中断例程内部用传递进来的参数决定执行哪个子程序
BIOS和DOS提供的中断例程,都用ah来传递内部子程序的编号
;int 10h 中断例程设置光标位置的功能
mov ah,2 ; (ah)=2表示调用10h号例程的2号子程序,功能为设置光标位置
mov bh,0 ; 提供参数,设置光标到第0页
mov dh,5 ; 提供行号
mov dl,12 ; 提供列号
int 10h ; 参数设置完毕后,调用中断例程
bh中页号的含义:内存中B800H~BFFFFH共32kB空间,为80*25彩色字符的显示缓冲区,彩色缓冲区分8页,显示器显示任意一页的内容,一般显示第0页
; 在光标位置显示字符功能
mov ah,9 ; 例程的9号子程序,在光标位置显示字符
mov al,'a' ; 字符
mov bl,7 ; 颜色属性
mov bh,0 ; 第0页
mov cx,3 ; 字符重复个数
int 10h ; 调用
bl的颜色属性设置与之前的显存中的属性字节的格式相同
编程,在屏幕5行12列显示3个红底高亮闪烁绿色的’a’
assume cs:code
code segment
mov ah,2 ; 设置光标位置
mov bh,0
mob dh,5
mov dl,12
int 10h
mov ah,9 ; 在光标位置显示字符
mov al,'a'
mov bl,11001010b
mov bh,0
mov cx,3
int 10h
mov ax,4c00h
int 21h
code ends
end
13.7 DOS中断例程应用
int21h是DOS提供的中断例程,其中包含了DOS提供给程序员在编程时调用的子程序
我们之前一直实验的是int21h的4ch号功能,即程序返回功能
mov ah,4c ; 程序返回
mov al,0 ; 提供参数,返回值
int 21h
; 我们常写为
mov ax,4c00h
int 21h
int21h中断例程中有显示字符串的功能
编程,在屏幕的5行12列显示字符串
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
int 21h
mov ax,4c00h
int 21h
code ends
end start
如果字符串较长,遇到行尾,程序自动转到下一行开头继续显示,如果到了最后一行,还能自动上卷一行