1.INT指令
- int指令格式為:int n,n為中斷碼的類(lèi)型,功能是引發(fā)對(duì)應(yīng)中斷碼的中斷
- int指令執(zhí)行的時(shí)候分為四步:
(1)從中斷向量表中取得n號(hào)中斷所對(duì)應(yīng)的程序入口地址
(2)將標(biāo)志寄存器入棧,然后設(shè)置TF和IF位的值為0
(3)CS和IP依次序入棧
(4)跳轉(zhuǎn)到程序入口地址(將IP設(shè)置為n* 4,將CS設(shè)置為n *4+2) - 所以int指令其實(shí)從效果上來(lái)看,跟call指令有些相似,都是保存現(xiàn)場(chǎng),調(diào)用一段程序
2.編寫(xiě)供應(yīng)用程序調(diào)用的中斷程序的方法
(1)實(shí)現(xiàn)中斷程序功能
(2)將中斷程序安裝在0000:0200處(上一講說(shuō)過(guò)中斷向量表的0000:0200~0000:02FF位置一般是空白的)
(3)設(shè)置中斷向量表,使發(fā)生對(duì)應(yīng)中斷的中斷號(hào)對(duì)應(yīng)到編寫(xiě)出來(lái)的中斷程序(一個(gè)表項(xiàng)兩個(gè)字)
注意:
(1)如果想要在中斷程序執(zhí)行完畢以后返回到原來(lái)程序執(zhí)行的位置,可以調(diào)用iret指令返回。(iret指令表示將IP,CS和標(biāo)志寄存器依次出棧后跳轉(zhuǎn))int指令和iret指令的配套使用同,call指令和ret指令配套使用有相似之處.
(2)一般在編寫(xiě)中斷例程和子程序的時(shí)候,我們都會(huì)將程序要用到寄存器先push到棧中保存起來(lái),以免影響主程序的功能
3.用中斷例程完成loop指令的功能(int,iret指令對(duì)應(yīng)棧機(jī)制的深入理解)
示例代碼:
;數(shù)據(jù)傳送示例代碼,調(diào)用中斷7cH
assume cs:code
code segment
start:
mov ax,0b800H
mov es,ax
mov di,160*12 ; 設(shè)置顯存位置
mov bx,offset s-offset se ; BX寄存器向子程序中傳遞se到s的偏移值
mov cx,80 ;循環(huán)打印80個(gè)‘!’
S:
mov byte ptr es:[di],'!'
add di,2
int 7cH ; 跳轉(zhuǎn)到中斷號(hào)為7c的中斷處理程序中去,實(shí)現(xiàn)循環(huán)到S
se: nop
mov ax,4c00H
int 21H
code ends
end start
; 7cH中斷例程
push bp ; 此程序?qū)⒁玫絙p,故先保存bp的值
mov bp,sp
dec cx ; 實(shí)現(xiàn)loop指令的CX減1
jcxz lpret ;
add [bp+2],bx ; 如果不等于0,則返回到開(kāi)始的地方
lpret:
pop bp
iret
解釋?zhuān)?/strong>
(1)在執(zhí)行中斷指令int 7cH時(shí),我們將標(biāo)志寄存器,CS和IP都?jí)喝肓藯V校藭r(shí)棧頂存放的應(yīng)該是程序正常執(zhí)行下一條指令的偏移位置。
(2)我們?cè)谥袛嗬讨杏胋p記錄例程開(kāi)始時(shí)棧頂?shù)奈恢?/strong>(其實(shí)這個(gè)程序可以不用bp,但是例程中是有可能修改sp的值的,為嚴(yán)謹(jǐn)我們還是將bp入棧),bx從外面?zhèn)鬟f進(jìn)來(lái)了外程序段的偏移值。
(3)我們看到中斷例程的add那一條指令,其實(shí)就是將棧頂?shù)南乱粋€(gè)元素(也就是IP的值)加上了外程序段偏移值bx,從而實(shí)現(xiàn)了修改IP,實(shí)現(xiàn)loop
4.BIOS和DOS提供的中斷例程
BIOS程序(Basic I/O System)放在計(jì)算機(jī)系統(tǒng)板的ROM中,主要包括:
(1)硬件系統(tǒng)檢測(cè)和初始化程序
(2)提供外部中斷和內(nèi)部中斷例程
(3)用于對(duì)硬件設(shè)備進(jìn)行I/O操作的中斷例程
(4)其他和硬件系統(tǒng)相關(guān)的中斷例程BIOS和DOS均提供了中斷例程,從操作系統(tǒng)角度看,DOS的中斷例程就是操作系統(tǒng)提供給程序員的編程資源。在DOS和硬件設(shè)備相關(guān)的中斷例程中,一般都調(diào)用了BIOS的中斷例程。
BIOS和DOS提供的中斷例程的安裝:
(1)開(kāi)機(jī)的瞬間,CPU一加電,就會(huì)初始化CS=FFFFH,IP=0,自動(dòng)從FFFF:0單元(CPU開(kāi)機(jī)執(zhí)行指令)開(kāi)始執(zhí)行程序,這個(gè)位置有一條跳轉(zhuǎn)指令,會(huì)跳轉(zhuǎn)到BIOS程序中執(zhí)行系統(tǒng)檢測(cè)和初始化指令。
(2)系統(tǒng)檢測(cè)完畢后,初始化程序?qū)?strong>建立BIOS所支持的中斷向量表(即將BIOS提供的中斷例程登記在中斷向量表中)
(3)硬件檢測(cè)和初始化完成以后,執(zhí)行int 19H,進(jìn)行操作系統(tǒng)的引導(dǎo)。從此計(jì)算機(jī)交給操作系統(tǒng)(DOS)控制
(4)DOS啟動(dòng)完成以后,除了完成其他工作,還會(huì)將DOS本身提供的中斷例程裝入內(nèi)存,并建立相應(yīng)中斷向量。(有的DOS中斷例程是調(diào)用了BIOS的中斷例程)
5.BIOS提供的中斷例程應(yīng)用舉例
- int 10H 中斷例程是BIOS提供的中斷例程,其中包含了多個(gè)和屏幕輸出相關(guān)的子例程(子例程:一般來(lái)說(shuō)一個(gè)可供程序員調(diào)用的例程中包含了許多個(gè)子程序,稱(chēng)作子例程)。中斷例程的內(nèi)部接受外部傳入的參數(shù),來(lái)決定執(zhí)行哪一個(gè)子程序。在BIOS和DOS提供的中斷例程中,都用ah寄存器來(lái)傳遞內(nèi)部子程序編號(hào)。
代碼舉例:
以下代碼實(shí)現(xiàn)把光標(biāo)設(shè)置到第0頁(yè),第5行,第12列
mov ah,2 ; 調(diào)用2號(hào)子程序,設(shè)置光標(biāo)
mov bh,0 ; 在第0頁(yè)
mov dh,5 ; 行號(hào)為5
mov dl,12 ; 列號(hào)為12
int 10H
(書(shū)中還例舉出當(dāng)ah=9的時(shí)候,10號(hào)中斷可以實(shí)現(xiàn)在光標(biāo)處顯示字符的功能,更多的BIOS中斷可以參考網(wǎng)上資料)
- int 21H中斷例程是DOS提供的中斷例程,其中包含了許多DOS提供給程序員在編程時(shí)調(diào)用的子程序。如我們經(jīng)常用到的程序返回功能:
mov ax,4c00H
int 21H
這個(gè)語(yǔ)句實(shí)際上是:
mov ah,4cH ;調(diào)用4c號(hào)子程序,功能是程序返回
mov al,0 ; 程序的返回值為0
int 21H
代碼舉例:
以下代碼實(shí)現(xiàn)在光標(biāo)位置顯示字符串。(21H中斷號(hào)的9號(hào)子程序,可以實(shí)現(xiàn)此功能,它將會(huì)輸出ds:dx指向的字符串,字符串以‘$’結(jié)尾)
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 ; 設(shè)置光標(biāo)位置
int 10H
mov ax,data
mov ds,ax
mov dx,0
mov ah,9
int 21H ; 調(diào)用光標(biāo)位置顯示字符串
mov ax,4c00H
int 21H
code ends
end start
附:實(shí)驗(yàn)說(shuō)明
要求:編寫(xiě)一個(gè)程序分別在屏幕的第2、4、6、8行顯示4句英文詩(shī)(詩(shī)句在數(shù)據(jù)中給出)
實(shí)驗(yàn)參考代碼:
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 ; 頁(yè)號(hào)
mov dh,ds:[si] ; 行號(hào)
mov dl,0 ; 列號(hào)
mov ah,2 ; 采用10號(hào)中斷的2號(hào)子程序(將光標(biāo)設(shè)置在指定位置)
int 10H
mov dx,ds:[bx] ; 參數(shù)dx傳入21號(hào)中斷的9號(hào)子程序(ds:dx指向要顯示字符串的位置,以‘$’結(jié)尾)
mov ah,9
int 21H
inc si
add bx,2
loop ok
mov ax,4c00H
int 21H
code ends
end start
實(shí)驗(yàn)截圖: