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