用匯編編寫DOS下的記憶體駐留程式(3) (轉)
用匯編編寫DOS下的記憶體駐留程式(3) (轉)[@more@] 三 中斷向量
3.1 IBM PC提供的中斷
IBM PC有兩種基本形態的中斷.如果是由外圍裝置所產生的中斷就叫做中斷(Hardware interrupt),譬如:鍵盤,機和時鐘等外圍裝置都可以產生硬體中斷.外圍裝置所產生的中斷訊號都連線到中斷控制器,中斷控制器可以根據它們之間的重要性來安排優先順序,以便使有效地處理這些硬體訊號.另一種中斷是中斷(Software interrupt),軟體中斷也叫做陷井(Trap),它是由中的軟體所產生.雖然軟體包中斷的處理方式和硬體中斷完全相同,但是通常軟體中斷是希望執行操作所提供的服務.
表3.1是IBM PC所提供的中斷,這些中斷是根據中斷號碼和中斷向量(Interrupt vector)排列.
IBM PC的或是編寫應用的程式人員很少會直接接觸到硬體中斷,除非是使用某些特殊的硬體,或是需要較嚴格的要求時,最常被修改的硬體中斷是敲鍵盤所產生的中斷(9H),尤其是文字編輯的程式.大體而言,只有硬體設計者基是系統程式人員才會注意到所有在硬體中斷;編寫駐留程式的設計人員則只使用到部分硬體中斷而已,尤其是:鍵盤中斷和計時器(Timer)的中斷.
反之,軟體中斷對於任何編寫匯序的人,甚至對編寫高階語言程式的人都相當的重要.軟體中斷是應用程式進入到IBM PC的介面,經由這些介面應用程式才可以執行所要求的系統服務.
其中軟體中斷中最重要,同時也是最常被語言師所用到是DINT 21H.這個中斷是執行DOS系統的軟體中斷,它可以讓應用程式執行任何DOS的操作.
接下來最有用的軟體中斷是ROM-(基本輸入輸出系統)所提供的中斷.這些軟體中斷是IBM PC所提供的的低層次服務,譬如:鍵盤輸入,顯示器輸出和磁碟機的輸入與輸出等.
3.2 鍵盤輸入的方法
以下就以IBM PC從鍵盤讀取字元為例子,來說明中斷的工作方式.IBM PC從鍵盤讀取字元時,使用了兩種不同形式中斷,亦即:硬體中斷和軟體中斷.當使用者從鍵盤敲下一個鍵時,鍵盤的線路就會送出一個訊號.這個訊號會造成硬體中斷髮生,從而觸發低層次的鍵盤中斷處理程式開始執行.這個中斷處理程式馬上從鍵盤的硬體讀取使用者所敲入的字元,然後把它放到一個佇列中,如果這個佇列填滿時,鍵盤中斷處理程式會使IBM PC發出一聲響.鍵盤中斷處理程式做完這些事情之後,它就把控制權交還給原先被中斷的程式.如果有一個程式希望從鍵盤讀取一個字元時,它就發出適當的軟體中斷訊號,這時候就由相對應的中斷處理程式去檢查鍵盤佇列,並且傳回佇列中的第一個字元.
上面所介紹的鍵盤輸入工作方式,在中斷系統中很普遍地採用.這和做法可以把實際上需要輸入的應用程式和實際上執行輸入的處理部分分開來.這種做法也可以用在其它不同形式的輸入和輸出外圍裝置.
3.3 改變輸入向量
中斷向量儲存在IBM PC最前面的400H個位元組中.每一個向量的長度是四個位元組組成,這四個位元組內所存放的是中斷處理程式執行的地址值.其中前兩個位元組包含地址值的位移(Offset)部分,後面的兩個位元組則包含了段(Segment)部分.
中斷向量有兩種修改方法.可以直接地設定中斷向量的地址值,或是使用DOS所提供的系統呼叫設定中斷向量的地址值.
3.3.1 直接設定中斷向量
因為中斷向量只是存放地址值的位置,因此我們可以直接地把地址存放到儲存位置中.以下是一個小例子:
mov ax,0
mov es,ax
mov ptr es:24,offset Keyboard
mov word ptr es:26,seg Keyboard
在許多情況下,上面的程式都可以正確地執行.但是如果上面的程式正在執行時突然敲下一個鍵的話,就可能會問題;而最糟的情 況是發生:第三個MOV已經執行完畢,而第四個MOV尚未執行時.如果在此時敲下任何鍵的話,鍵盤中斷向量都沒有任何意義,而造成整個系 統當機.因此我們可以在設定中斷向量時,讓中斷無效,譬如:
mov ax,0
mov es,ax
cli
mov word ptr es:24,offset Keyboard
mov word ptr es:26,seg Keyboard
上面的做法在大部分的情況下都可以正確地執行.但是CLI這個指令無法停止NMI中斷(不可遮蔽中斷),因此如果發生NMI中斷時就 沒用辦法.下面的這一種做法雖然比較複雜,但是對於所有的中斷都有效,這包括了NMI中斷在內:
mov word ptr kbd-ptr[0],offset Keyboard
mov word ptr kbd-ptr[2],seg Keyboard
mov di,0 ;Use Di to Set ES to zero
mov es,di ;Set ES to destination segment
mov di,24 ;Set DI to destination offset
mov si,offset kbdptr ;set SI to offset
mov cx,2 ;Set word count to 2
cld ;Set direction to forward
cli ;Disable interrupts
rep movsw ;Copy the new vector
sti ;Enable interrupts
kbdptr dd ?
上面的程式中,kbdptr是兩個位元組(WORD)的指標(Pointer),其中包含了鍵盤 中斷處理程式的起始志趣值.REP這個指令將根據寄存 器CX所設定的次數來重複執行MOVSW,而整個指令就如同單一的指令一樣.NMI中斷不能夠發生在一個完整的指令中.因為地址值搬移的操 作都能包含在一個單一指令中,因此可以免除任何中斷的干擾.
3.3.2 使用DOS來設定中斷向量
因為要想地設定中斷向量需要一些技巧,因此DOS提供了一項特殊的服務,以幫助程式人員安全地設定中斷向量,如果只使用 DOS所提供的這項服務來設定中斷向量的話,那麼就不必擔心會發生前面所敘述的差錯.DOS同時也提供了:讀取中斷向量的服務.因為讀 取中斷向量的內容不會修改系統的狀態;因此若直接寫程式讀取,也很安全.但是如果你要自己直接讀取中斷向量的內容時,就必須計算 出中斷向量的位置.而DOS已經提供了這項服務.
使用DOS所提供的系統呼叫,來讀取中斷向量的內容時,必須利用INT 21H中的35H(讀取中斷向量),這個函式熱氣向量號碼來 計算中斷向量的地址,然後返回其中的內容.以下就是一個例子:
Old_Keyboard_IO dd ?
mov al,16h
mov ah,35h
int 21h
mov word ptr Old_Keyboard_IO,bx ;Offset of interrupt handler
mov word ptr Old_Keyboard_IO,es ;Segment of interrupt handler
用DOS來設定中斷向量例子:
New_Keyboard_IO dd ?
mov word ptr New_Keyboard_IO,bx ;Offset of interrupt handler
mov word ptr New_Keyboard_IO,es ;Segment of interrupt handler
mov al,16h
mov ah,25h
int 21h
3.4 檢查中斷向量
這裡都是採用COM格式程式設計,可以建立一個BAT來處理寫好的程式,以減少擊鍵次數.設BAT檔名為MAKE.BAT:
MASM %1
LINK %1
EXE2BIN %1.EXE %1.COM
如果寫好的程式名為MACRO.ASM,則可敲入:
C:MAKE MACRO.ASM
即可.
3.5 顯示中斷向量
下面這個例子可以列出所有的重要的中斷向量內容,在剛剛開啟PC時,並且沒有執行任何駐留程式時,可以發現所有的中斷向量段值都相同,這些地址值所存放的是ROM的程式.當你修改中斷向量之後,就可以利用這個程式觀察到中斷向量的變化.以下就是IVEC.ASM的內容:
cseg segment para public 'CODE'
org 100h
jmp start
assume cs:cseg,ds:cseg
start:
mov bx,cs ;Make data seg be the same as
mov ds,bx ;the code seg
call vectors
waitIn:
mov ah,0bh
int 21h
cmp al,0ffh
jne waitIn
mov ah,4ch
int 21h
;****************************************************************************
;Scan through display table,prinying two vectors per line
;If any record has an interrupt #=zero,this indicates
;end of the table.
;****************************************************************************
mov di,offset disptab ;Pointer to start of table
mov dh,0 ;Zero out top half of DX
vl:
mov dl,[di] ;Get the interrupt number
cmp dl,0 ;If it's zero,we are done
je vdone ;so exit loop
add di,1 ;Advance pointer 1 byte
mov si,[di] ;Get pointer to description
call dvector ;Call the display routine
add di,2 ;Get the interrupt number
mov dl,[di] ;Advance to the next record
cmp dl,0 ;If it's zero,we are done
je vdone ;so exit loop
add di,1 ;Advance pointer 1 byte
mov si,[di] ;get pointer to description
call dvector ;Call the display routine
add di,2 ;Advance to the next record
jmp vloop
vdone: ;Print final CRLF
ret
vectors endp
;----------------------------------------------------------------------------
;Displays an interrupt vector.Display is in the foof
;,,:
;where,and
;are all dexadecimal numbers
;Call with
;DX -interrupt number
;DS:SI -pointer to banner string
;----------------------------------------------------------------------------
dvector proc near
call dstring ;Display the string in DS:SI
call yte ;Display the byte in DL
call dspace ;Display a space
call dspace
;
mov al,dl ;move the interrupt number to AL
mov ah,35h ;Function is Get interrupt vector
int 21h
mov dx,bx ;Move BX to DX so we can display
call ddword ;double-word in ES:DX
call dEndFra
call dcrlf ;Display a newline
ret
dvector endp
;----------------------------------------------------------------------------
;DS:SI points to ASCII string to be printed
;----------------------------------------------------------------------------
dstring proc near
push si
push ax
dis: mov al,[si] ;Fetch the next character
cmp al,0 ;If it's zero,we are done
je disdone
call dchar ;If not,point it
inc si ;Advance pointer to nest char
jmp dis
disdone:pop ax
pop si
ret
dstring endp
;----------------------------------------------------------------------------
;ES:DX contains double word to be displayed
;----------------------------------------------------------------------------
ddword proc near
push dx ;Save offset temporarily
mov dx,es ;Move segment to DX
call dsword ;Display segment
call dcolon ;Print a ";"
; call dcrlf
pop dx ;Restore offset to DX
call dsword ;Display offset
ret
ddword endp
;----------------------------------------------------------------------------
;DX containes single word to be displayed
;----------------------------------------------------------------------------
dsword proc near
push dx ;Save low byte temporarily
mov dl,dh ;Move high byte to low byte
call dbyte ;Display high byte
pop dx ;Restore low byte to DL
call dbyte ;Display low byte
ret
dsword endp
;----------------------------------------------------------------------------
;DL contains byte to be displayed
;----------------------------------------------------------------------------
dbyte proc near
push ax ;Save any registers used
push dx
push si
push dx ;Save low nybble temporarily
push cx ;Save CX
mov cl,4 ;Set shift count to 4
shr dx,cl ;Shift high nybble into low nybble
and dx,0fh ;Mask out all but low nybble
mov si,dx ;Use low nybble as index into
mov al,hextab[si] ;hexadecimal character table
call dchar ;Display character
pop cx ;Restore CX
pop dx ;Restore low nybble
and dx,0fh ;Mask out all but low nybble
mov si,dx ;Use low nybble as an index into
mov al,hextab[si] ;hexadecimal character table
call dchar ;Display character
pop si ;Restore registers
pop dx
pop ax
ret
dbyte endp
;----------------------------------------------------------------------------
;Display a ":"
;----------------------------------------------------------------------------
dcolon proc near
mov al,':'
call dchar
ret
dcolon endp
;----------------------------------------------------------------------------
;Display a " "
;----------------------------------------------------------------------------
dspace proc near
mov al,' '
call dchar
ret
dspace endp
;----------------------------------------------------------------------------
;Display a Carriage Return/Line Feed
;----------------------------------------------------------------------------
dcrlf proc near
mov al,0dh
call dchar
mov al,0ah
call dchar
ret
dcrlf endp
;----------------------------------------------------------------------------
;Display the character contained in AL
;----------------------------------------------------------------------------
dchar proc near
push ax
push bx
mov bh,1
mov ah,0eh
int 10h
pop bx
pop ax
ret
dchar endp
;----------------------------------------------------------------------------
;Data define
;----------------------------------------------------------------------------
hextab db '0123456789ABCDEF',0
disptab db 05h ;Print screen
dw v05
db 19h ;Bootstrap loader
dw v19
db 08h ;Timer tick
dw v08
db 1ah ;Real_time clock
dw v1a
db 09h ;Keyboard input
dw v09
db 1bh ;CTRL_Break handler
dw v1b
db 0bh ;Comm.port 1
dw v0b
db 1ch ;Timer control
dw v1c
db 0ch ;Comm.port 0
dw v0c
db 1dh ;Pointer to vo parameter table
dw v1d
db 0dh ;Hard disk controller
dw v0d
db 1eh ;Pointer to disk parameter table
dw v1e
db 0eh ;Floppy disk controller
dw v0e
db 1fh ;Pointer graphics character table
dw v1f
db 0fh ;Printer controller
dw v0f
db 20h ;Program tenate
dw v20
db 10h ;Video
dw v10
db 21h ;DOS universal function
dw v21
db 11h ;Equipment check
dw v11
db 22h ;Pointer to termination handler
dw v22
db 12h ;Memorey size check
dw v12
db 23h ;Pointer to Ctrl_C handler
dw v23
db 13h ;Disk driver
dw v13
db 24h ;Pointer to critical error handler
dw v24
db 14h ;Communications driver
dw v14
db 25h ;Absolute disk read
dw v25
db 15h ;Cassette driver
dw v15
db 26h ;Absolute disk write
dw v26
db 16h ;Keyboard driver
dw v16
db 27h ;Terminate and stay resident
dw v27
db 17h ;Printer driver
dw v17
db 2fh ;Print spooler
dw v2f
db 18h ;Rom basic
dw v18
db 0
dw 0
v05 db 186,5 dup (20h),'Print screen:',26 dup (20h),0
v08 db 186,5 dup (20h),'Timer tick controller:',17 dup (20h),0
v09 db 186,5 dup (20h),'Keyboard input:',24 dup (20h),0
v0b db 186,5 dup (20h),'Communication port 1:',18 dup (20h),0
v0c db 186,5 dup (20h),'Communication port 0:',18 dup (20h),0
v0d db 186,5 dup (20h),'Hard disk controller:',18 dup (20h),0
v0e db 186,5 dup (20h),'Floppy disk controller:',16 dup (20h),0
v0f db 186,5 dup (20h),'Printer controller:',20 dup (20h),0
v10 db 186,5 dup (20h),'Video driver:',26 dup (20h),0
v11 db 186,5 dup (20h),'Equipment check:',23 dup (20h),0
v12 db 186,5 dup (20h),'Memory size check:',21 dup (20h),0
v13 db 186,5 dup (20h),'Disk driver:',27 dup (20h),0
v14 db 186,5 dup (20h),'Communication driver:',18 dup (20h),0
v15 db 186,5 dup (20h),'Cassette driver:',23 dup (20h),0
v16 db 186,5 dup (20h),'Keyboard driver:',23 dup (20h),0
v17 db 186,5 dup (20h),'Printer driver:',24 dup (20h),0
v18 db 186,5 dup (20h),'ROM BASIC:',29 dup (20h),0
v19 db 186,5 dup (20h),'Bootstrap loader:',22 dup (20h),0
v1a db 186,5 dup (20h),'Real_time clock:',23 dup (20h),0
v1b db 186,5 dup (20h),'Ctrl_break handler:',20 dup (20h),0
v1c db 186,5 dup (20h),'Timer control:',25 dup (20h),0
v1d db 186,5 dup (20h),'Video parameter table:',17 dup (20h),0
v1e db 186,5 dup (20h),'Disk parameter:',24 dup (20h),0
v1f db 186,5 dup (20h),'Graphic character table:',15 dup (20h),0
v20 db 186,5 dup (20h),'Programe terminate:',20 dup (20h),0
v21 db 186,5 dup (20h),'DOS universal function:',16 dup (20h),0
v22 db 186,5 dup (20h),'Terminate vector:',22 dup (20h),0
v23 db 186,5 dup (20h),'Ctrl_C vector:',25 dup (20h),0
v24 db 186,5 dup (20h),'Critical error vector:',17 dup (20h),0
v25 db 186,5 dup (20h),'Absolute disk read:',20 dup (20h),0
v26 db 186,5 dup (20h),'Absolute disk write:',19 dup (20h),0
v27 db 186,5 dup (20h),'Terminate and stay resident:',11 dup (20h),0
v2f db 186,5 dup (20h),'Print spooler:',25 dup (20h),0
cseg ends
end start
3.1 IBM PC提供的中斷
IBM PC有兩種基本形態的中斷.如果是由外圍裝置所產生的中斷就叫做中斷(Hardware interrupt),譬如:鍵盤,機和時鐘等外圍裝置都可以產生硬體中斷.外圍裝置所產生的中斷訊號都連線到中斷控制器,中斷控制器可以根據它們之間的重要性來安排優先順序,以便使有效地處理這些硬體訊號.另一種中斷是中斷(Software interrupt),軟體中斷也叫做陷井(Trap),它是由中的軟體所產生.雖然軟體包中斷的處理方式和硬體中斷完全相同,但是通常軟體中斷是希望執行操作所提供的服務.
表3.1是IBM PC所提供的中斷,這些中斷是根據中斷號碼和中斷向量(Interrupt vector)排列.
IBM PC的或是編寫應用的程式人員很少會直接接觸到硬體中斷,除非是使用某些特殊的硬體,或是需要較嚴格的要求時,最常被修改的硬體中斷是敲鍵盤所產生的中斷(9H),尤其是文字編輯的程式.大體而言,只有硬體設計者基是系統程式人員才會注意到所有在硬體中斷;編寫駐留程式的設計人員則只使用到部分硬體中斷而已,尤其是:鍵盤中斷和計時器(Timer)的中斷.
反之,軟體中斷對於任何編寫匯序的人,甚至對編寫高階語言程式的人都相當的重要.軟體中斷是應用程式進入到IBM PC的介面,經由這些介面應用程式才可以執行所要求的系統服務.
其中軟體中斷中最重要,同時也是最常被語言師所用到是DINT 21H.這個中斷是執行DOS系統的軟體中斷,它可以讓應用程式執行任何DOS的操作.
接下來最有用的軟體中斷是ROM-(基本輸入輸出系統)所提供的中斷.這些軟體中斷是IBM PC所提供的的低層次服務,譬如:鍵盤輸入,顯示器輸出和磁碟機的輸入與輸出等.
3.2 鍵盤輸入的方法
以下就以IBM PC從鍵盤讀取字元為例子,來說明中斷的工作方式.IBM PC從鍵盤讀取字元時,使用了兩種不同形式中斷,亦即:硬體中斷和軟體中斷.當使用者從鍵盤敲下一個鍵時,鍵盤的線路就會送出一個訊號.這個訊號會造成硬體中斷髮生,從而觸發低層次的鍵盤中斷處理程式開始執行.這個中斷處理程式馬上從鍵盤的硬體讀取使用者所敲入的字元,然後把它放到一個佇列中,如果這個佇列填滿時,鍵盤中斷處理程式會使IBM PC發出一聲響.鍵盤中斷處理程式做完這些事情之後,它就把控制權交還給原先被中斷的程式.如果有一個程式希望從鍵盤讀取一個字元時,它就發出適當的軟體中斷訊號,這時候就由相對應的中斷處理程式去檢查鍵盤佇列,並且傳回佇列中的第一個字元.
上面所介紹的鍵盤輸入工作方式,在中斷系統中很普遍地採用.這和做法可以把實際上需要輸入的應用程式和實際上執行輸入的處理部分分開來.這種做法也可以用在其它不同形式的輸入和輸出外圍裝置.
3.3 改變輸入向量
中斷向量儲存在IBM PC最前面的400H個位元組中.每一個向量的長度是四個位元組組成,這四個位元組內所存放的是中斷處理程式執行的地址值.其中前兩個位元組包含地址值的位移(Offset)部分,後面的兩個位元組則包含了段(Segment)部分.
中斷向量有兩種修改方法.可以直接地設定中斷向量的地址值,或是使用DOS所提供的系統呼叫設定中斷向量的地址值.
3.3.1 直接設定中斷向量
因為中斷向量只是存放地址值的位置,因此我們可以直接地把地址存放到儲存位置中.以下是一個小例子:
mov ax,0
mov es,ax
mov ptr es:24,offset Keyboard
mov word ptr es:26,seg Keyboard
在許多情況下,上面的程式都可以正確地執行.但是如果上面的程式正在執行時突然敲下一個鍵的話,就可能會問題;而最糟的情 況是發生:第三個MOV已經執行完畢,而第四個MOV尚未執行時.如果在此時敲下任何鍵的話,鍵盤中斷向量都沒有任何意義,而造成整個系 統當機.因此我們可以在設定中斷向量時,讓中斷無效,譬如:
mov ax,0
mov es,ax
cli
mov word ptr es:24,offset Keyboard
mov word ptr es:26,seg Keyboard
上面的做法在大部分的情況下都可以正確地執行.但是CLI這個指令無法停止NMI中斷(不可遮蔽中斷),因此如果發生NMI中斷時就 沒用辦法.下面的這一種做法雖然比較複雜,但是對於所有的中斷都有效,這包括了NMI中斷在內:
mov word ptr kbd-ptr[0],offset Keyboard
mov word ptr kbd-ptr[2],seg Keyboard
mov di,0 ;Use Di to Set ES to zero
mov es,di ;Set ES to destination segment
mov di,24 ;Set DI to destination offset
mov si,offset kbdptr ;set SI to offset
mov cx,2 ;Set word count to 2
cld ;Set direction to forward
cli ;Disable interrupts
rep movsw ;Copy the new vector
sti ;Enable interrupts
kbdptr dd ?
上面的程式中,kbdptr是兩個位元組(WORD)的指標(Pointer),其中包含了鍵盤 中斷處理程式的起始志趣值.REP這個指令將根據寄存 器CX所設定的次數來重複執行MOVSW,而整個指令就如同單一的指令一樣.NMI中斷不能夠發生在一個完整的指令中.因為地址值搬移的操 作都能包含在一個單一指令中,因此可以免除任何中斷的干擾.
3.3.2 使用DOS來設定中斷向量
因為要想地設定中斷向量需要一些技巧,因此DOS提供了一項特殊的服務,以幫助程式人員安全地設定中斷向量,如果只使用 DOS所提供的這項服務來設定中斷向量的話,那麼就不必擔心會發生前面所敘述的差錯.DOS同時也提供了:讀取中斷向量的服務.因為讀 取中斷向量的內容不會修改系統的狀態;因此若直接寫程式讀取,也很安全.但是如果你要自己直接讀取中斷向量的內容時,就必須計算 出中斷向量的位置.而DOS已經提供了這項服務.
使用DOS所提供的系統呼叫,來讀取中斷向量的內容時,必須利用INT 21H中的35H(讀取中斷向量),這個函式熱氣向量號碼來 計算中斷向量的地址,然後返回其中的內容.以下就是一個例子:
Old_Keyboard_IO dd ?
mov al,16h
mov ah,35h
int 21h
mov word ptr Old_Keyboard_IO,bx ;Offset of interrupt handler
mov word ptr Old_Keyboard_IO,es ;Segment of interrupt handler
用DOS來設定中斷向量例子:
New_Keyboard_IO dd ?
mov word ptr New_Keyboard_IO,bx ;Offset of interrupt handler
mov word ptr New_Keyboard_IO,es ;Segment of interrupt handler
mov al,16h
mov ah,25h
int 21h
3.4 檢查中斷向量
這裡都是採用COM格式程式設計,可以建立一個BAT來處理寫好的程式,以減少擊鍵次數.設BAT檔名為MAKE.BAT:
MASM %1
LINK %1
EXE2BIN %1.EXE %1.COM
如果寫好的程式名為MACRO.ASM,則可敲入:
C:MAKE MACRO.ASM
即可.
3.5 顯示中斷向量
下面這個例子可以列出所有的重要的中斷向量內容,在剛剛開啟PC時,並且沒有執行任何駐留程式時,可以發現所有的中斷向量段值都相同,這些地址值所存放的是ROM的程式.當你修改中斷向量之後,就可以利用這個程式觀察到中斷向量的變化.以下就是IVEC.ASM的內容:
cseg segment para public 'CODE'
org 100h
jmp start
assume cs:cseg,ds:cseg
start:
mov bx,cs ;Make data seg be the same as
mov ds,bx ;the code seg
call vectors
waitIn:
mov ah,0bh
int 21h
cmp al,0ffh
jne waitIn
mov ah,4ch
int 21h
;****************************************************************************
;Scan through display table,prinying two vectors per line
;If any record has an interrupt #=zero,this indicates
;end of the table.
;****************************************************************************
mov di,offset disptab ;Pointer to start of table
mov dh,0 ;Zero out top half of DX
vl:
mov dl,[di] ;Get the interrupt number
cmp dl,0 ;If it's zero,we are done
je vdone ;so exit loop
add di,1 ;Advance pointer 1 byte
mov si,[di] ;Get pointer to description
call dvector ;Call the display routine
add di,2 ;Get the interrupt number
mov dl,[di] ;Advance to the next record
cmp dl,0 ;If it's zero,we are done
je vdone ;so exit loop
add di,1 ;Advance pointer 1 byte
mov si,[di] ;get pointer to description
call dvector ;Call the display routine
add di,2 ;Advance to the next record
jmp vloop
vdone: ;Print final CRLF
ret
vectors endp
;----------------------------------------------------------------------------
;Displays an interrupt vector.Display is in the foof
;
;where
;are all dexadecimal numbers
;Call with
;DX -interrupt number
;DS:SI -pointer to banner string
;----------------------------------------------------------------------------
dvector proc near
call dstring ;Display the string in DS:SI
call yte ;Display the byte in DL
call dspace ;Display a space
call dspace
;
mov al,dl ;move the interrupt number to AL
mov ah,35h ;Function is Get interrupt vector
int 21h
mov dx,bx ;Move BX to DX so we can display
call ddword ;double-word in ES:DX
call dEndFra
call dcrlf ;Display a newline
ret
dvector endp
;----------------------------------------------------------------------------
;DS:SI points to ASCII string to be printed
;----------------------------------------------------------------------------
dstring proc near
push si
push ax
dis: mov al,[si] ;Fetch the next character
cmp al,0 ;If it's zero,we are done
je disdone
call dchar ;If not,point it
inc si ;Advance pointer to nest char
jmp dis
disdone:pop ax
pop si
ret
dstring endp
;----------------------------------------------------------------------------
;ES:DX contains double word to be displayed
;----------------------------------------------------------------------------
ddword proc near
push dx ;Save offset temporarily
mov dx,es ;Move segment to DX
call dsword ;Display segment
call dcolon ;Print a ";"
; call dcrlf
pop dx ;Restore offset to DX
call dsword ;Display offset
ret
ddword endp
;----------------------------------------------------------------------------
;DX containes single word to be displayed
;----------------------------------------------------------------------------
dsword proc near
push dx ;Save low byte temporarily
mov dl,dh ;Move high byte to low byte
call dbyte ;Display high byte
pop dx ;Restore low byte to DL
call dbyte ;Display low byte
ret
dsword endp
;----------------------------------------------------------------------------
;DL contains byte to be displayed
;----------------------------------------------------------------------------
dbyte proc near
push ax ;Save any registers used
push dx
push si
push dx ;Save low nybble temporarily
push cx ;Save CX
mov cl,4 ;Set shift count to 4
shr dx,cl ;Shift high nybble into low nybble
and dx,0fh ;Mask out all but low nybble
mov si,dx ;Use low nybble as index into
mov al,hextab[si] ;hexadecimal character table
call dchar ;Display character
pop cx ;Restore CX
pop dx ;Restore low nybble
and dx,0fh ;Mask out all but low nybble
mov si,dx ;Use low nybble as an index into
mov al,hextab[si] ;hexadecimal character table
call dchar ;Display character
pop si ;Restore registers
pop dx
pop ax
ret
dbyte endp
;----------------------------------------------------------------------------
;Display a ":"
;----------------------------------------------------------------------------
dcolon proc near
mov al,':'
call dchar
ret
dcolon endp
;----------------------------------------------------------------------------
;Display a " "
;----------------------------------------------------------------------------
dspace proc near
mov al,' '
call dchar
ret
dspace endp
;----------------------------------------------------------------------------
;Display a Carriage Return/Line Feed
;----------------------------------------------------------------------------
dcrlf proc near
mov al,0dh
call dchar
mov al,0ah
call dchar
ret
dcrlf endp
;----------------------------------------------------------------------------
;Display the character contained in AL
;----------------------------------------------------------------------------
dchar proc near
push ax
push bx
mov bh,1
mov ah,0eh
int 10h
pop bx
pop ax
ret
dchar endp
;----------------------------------------------------------------------------
;Data define
;----------------------------------------------------------------------------
hextab db '0123456789ABCDEF',0
disptab db 05h ;Print screen
dw v05
db 19h ;Bootstrap loader
dw v19
db 08h ;Timer tick
dw v08
db 1ah ;Real_time clock
dw v1a
db 09h ;Keyboard input
dw v09
db 1bh ;CTRL_Break handler
dw v1b
db 0bh ;Comm.port 1
dw v0b
db 1ch ;Timer control
dw v1c
db 0ch ;Comm.port 0
dw v0c
db 1dh ;Pointer to vo parameter table
dw v1d
db 0dh ;Hard disk controller
dw v0d
db 1eh ;Pointer to disk parameter table
dw v1e
db 0eh ;Floppy disk controller
dw v0e
db 1fh ;Pointer graphics character table
dw v1f
db 0fh ;Printer controller
dw v0f
db 20h ;Program tenate
dw v20
db 10h ;Video
dw v10
db 21h ;DOS universal function
dw v21
db 11h ;Equipment check
dw v11
db 22h ;Pointer to termination handler
dw v22
db 12h ;Memorey size check
dw v12
db 23h ;Pointer to Ctrl_C handler
dw v23
db 13h ;Disk driver
dw v13
db 24h ;Pointer to critical error handler
dw v24
db 14h ;Communications driver
dw v14
db 25h ;Absolute disk read
dw v25
db 15h ;Cassette driver
dw v15
db 26h ;Absolute disk write
dw v26
db 16h ;Keyboard driver
dw v16
db 27h ;Terminate and stay resident
dw v27
db 17h ;Printer driver
dw v17
db 2fh ;Print spooler
dw v2f
db 18h ;Rom basic
dw v18
db 0
dw 0
v05 db 186,5 dup (20h),'Print screen:',26 dup (20h),0
v08 db 186,5 dup (20h),'Timer tick controller:',17 dup (20h),0
v09 db 186,5 dup (20h),'Keyboard input:',24 dup (20h),0
v0b db 186,5 dup (20h),'Communication port 1:',18 dup (20h),0
v0c db 186,5 dup (20h),'Communication port 0:',18 dup (20h),0
v0d db 186,5 dup (20h),'Hard disk controller:',18 dup (20h),0
v0e db 186,5 dup (20h),'Floppy disk controller:',16 dup (20h),0
v0f db 186,5 dup (20h),'Printer controller:',20 dup (20h),0
v10 db 186,5 dup (20h),'Video driver:',26 dup (20h),0
v11 db 186,5 dup (20h),'Equipment check:',23 dup (20h),0
v12 db 186,5 dup (20h),'Memory size check:',21 dup (20h),0
v13 db 186,5 dup (20h),'Disk driver:',27 dup (20h),0
v14 db 186,5 dup (20h),'Communication driver:',18 dup (20h),0
v15 db 186,5 dup (20h),'Cassette driver:',23 dup (20h),0
v16 db 186,5 dup (20h),'Keyboard driver:',23 dup (20h),0
v17 db 186,5 dup (20h),'Printer driver:',24 dup (20h),0
v18 db 186,5 dup (20h),'ROM BASIC:',29 dup (20h),0
v19 db 186,5 dup (20h),'Bootstrap loader:',22 dup (20h),0
v1a db 186,5 dup (20h),'Real_time clock:',23 dup (20h),0
v1b db 186,5 dup (20h),'Ctrl_break handler:',20 dup (20h),0
v1c db 186,5 dup (20h),'Timer control:',25 dup (20h),0
v1d db 186,5 dup (20h),'Video parameter table:',17 dup (20h),0
v1e db 186,5 dup (20h),'Disk parameter:',24 dup (20h),0
v1f db 186,5 dup (20h),'Graphic character table:',15 dup (20h),0
v20 db 186,5 dup (20h),'Programe terminate:',20 dup (20h),0
v21 db 186,5 dup (20h),'DOS universal function:',16 dup (20h),0
v22 db 186,5 dup (20h),'Terminate vector:',22 dup (20h),0
v23 db 186,5 dup (20h),'Ctrl_C vector:',25 dup (20h),0
v24 db 186,5 dup (20h),'Critical error vector:',17 dup (20h),0
v25 db 186,5 dup (20h),'Absolute disk read:',20 dup (20h),0
v26 db 186,5 dup (20h),'Absolute disk write:',19 dup (20h),0
v27 db 186,5 dup (20h),'Terminate and stay resident:',11 dup (20h),0
v2f db 186,5 dup (20h),'Print spooler:',25 dup (20h),0
cseg ends
end start
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752019/viewspace-958645/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 用匯編編寫DOS下的記憶體駐留程式(5) (轉)記憶體
- 用匯編編寫DOS下的記憶體駐留程式(4) (轉)記憶體
- Billy Belceb病毒編寫教程(DOS篇)---駐留記憶體病毒記憶體
- SQL Server表駐留記憶體和檢測SQLServer記憶體
- Billy Belceb病毒編寫教程(DOS篇)---病毒編寫所需的軟體
- 用Delphi編寫DelTree程式 (轉)
- 動畫程式編寫——DirectDraw之旅(3)(轉)動畫
- [編寫高質量iOS程式碼的52個有效方法](八)記憶體管理(下)iOS記憶體
- 照片記憶編寫軟體:Memory Pictures for MacMac
- 用匯編輕鬆地寫基於對話方塊的程式 (轉)
- 用VC++編寫CGI程式 (轉)C++
- 用VB編寫抽獎程式 (轉)
- VC在windows下編寫用於序列通訊的程式 (轉)Windows
- Billy Belceb病毒編寫教程(DOS篇)有用的結構體結構體
- 用QT在Windows下編寫dll程式QTWindows
- 用Delphi編寫安裝程式(1) (轉)
- 用VB編寫標準CGI程式 (轉)
- 用 C++Builder 編寫 Tray 程式 (轉)C++UI
- 編寫優質無錯程式碼(3) (轉)
- dos下編譯執行java程式遇到的問題編譯Java
- 編寫Linux實用程式的藝術(轉)Linux
- 用VB編寫非同步多執行緒下載程式 (轉)非同步執行緒
- 在Unix下用C編寫curses程式的一些常用模組(轉)
- 一個dos下tc編的俄羅斯方塊源程式(附註釋) (轉)
- Billy Belceb病毒編寫教程(DOS篇)---保護你的程式碼
- 用VC++6.0編寫撥號程式 (轉)C++
- 為Linux 應用程式編寫 DLL(轉)Linux
- 編寫高效的MySQL應用(轉)MySql
- 如何用Java編寫一段程式碼引發記憶體洩露Java記憶體洩露
- 用匯編來實現OOP (轉)OOP
- Billy Belceb病毒編寫教程DOS篇---宣告
- Billy Belceb病毒編寫教程(DOS篇)---加密加密
- 編寫易讀的程式碼 (轉)
- 用 Delphi 編寫 VxD 裝置驅動程式(轉) (轉)
- [編寫高質量iOS程式碼的52個有效方法](七)記憶體管理(上)iOS記憶體
- vue3程式碼編寫Vue
- unix下編寫socket程式的一般步驟(轉)
- 用Java編寫ASP元件 (轉)Java元件