David.Ko

          Follow my heart!
          posts - 100, comments - 11, trackbacks - 0, articles - 0
             :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          用匯編編寫(xiě)DOS下的內(nèi)存駐留程序(3)

          Posted on 2007-09-30 08:20 David.Ko 閱讀(262) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): 病毒
          三 中斷矢量
          3.1 IBM PC提供的中斷
          IBM PC有兩種基本形態(tài)的中斷.如果是由外圍設(shè)備所產(chǎn)生的中斷就叫做硬件中斷(Hardware interrupt),譬如:鍵盤(pán),磁盤(pán)機(jī)和時(shí)鐘等外圍設(shè)備都可以產(chǎn)生硬件中斷.外圍設(shè)備所產(chǎn)生的中斷信號(hào)都連接到中斷控制器,中斷控制器可以根據(jù)它們之間的重要性來(lái)安排優(yōu)先順序,以便使CPU有效地處理這些硬件信號(hào).另一種中斷是軟件中斷(Software interrupt),軟件中斷也叫做陷井(Trap),它是由執(zhí)行中的軟件所產(chǎn)生.雖然軟件包中斷的處理方式和硬件中斷完全相同,但是通常軟件中斷是希望執(zhí)行操作系統(tǒng)所提供的服務(wù).
          表3.1是IBM PC所提供的中斷,這些中斷是根據(jù)中斷號(hào)碼和中斷矢量(Interrupt vector)排列.
          IBM PC的用戶(hù)或是編寫(xiě)應(yīng)用程序的程序人員很少會(huì)直接接觸到硬件中斷,除非是使用某些特殊的硬件,或是需要較嚴(yán)格的要求時(shí),最常被修改的硬件中斷是敲鍵盤(pán)所產(chǎn)生的中斷(9H),尤其是文本編輯的程序.大體而言,只有硬件設(shè)計(jì)者基是系統(tǒng)程序人員才會(huì)注意到所有在硬件中斷;編寫(xiě)內(nèi)存駐留程序的設(shè)計(jì)人員則只使用到部分硬件中斷而已,尤其是:鍵盤(pán)中斷和計(jì)時(shí)器(Timer)的中斷.
          反之,軟件中斷對(duì)于任何編寫(xiě)匯編程序的人,甚至對(duì)編寫(xiě)高級(jí)語(yǔ)言程序的人都相當(dāng)?shù)闹匾?軟件中斷是應(yīng)用程序進(jìn)入到IBM PC操作系統(tǒng)的接口,經(jīng)由這些接口應(yīng)用程序才可以執(zhí)行所要求的系統(tǒng)服務(wù).
          其中軟件中斷中最重要,同時(shí)也是最常被匯編語(yǔ)言程序設(shè)計(jì)師所用到是DOS INT 21H.這個(gè)中斷是執(zhí)行DOS系統(tǒng)調(diào)用的軟件中斷,它可以讓?xiě)?yīng)用程序執(zhí)行任何DOS的操作.
          接下來(lái)最有用的軟件中斷是ROM-BIOS(基本輸入輸出系統(tǒng))所提供的中斷.這些軟件中斷是IBM PC所提供的的低層次服務(wù),譬如:鍵盤(pán)輸入,顯示器輸出和磁盤(pán)機(jī)的輸入與輸出等.
          3.2 鍵盤(pán)輸入的方法
          以下就以IBM PC從鍵盤(pán)讀取字符為例子,來(lái)說(shuō)明中斷的工作方式.IBM PC從鍵盤(pán)讀取字符時(shí),使用了兩種不同形式中斷,亦即:硬件中斷和軟件中斷.當(dāng)使用者從鍵盤(pán)敲下一個(gè)鍵時(shí),鍵盤(pán)的線路就會(huì)送出一個(gè)信號(hào).這個(gè)信號(hào)會(huì)造成硬件中斷發(fā)生,從而觸發(fā)低層次的鍵盤(pán)中斷處理程序開(kāi)始執(zhí)行.這個(gè)中斷處理程序馬上從鍵盤(pán)的硬件讀取使用者所敲入的字符,然后把它放到一個(gè)隊(duì)列中,如果這個(gè)隊(duì)列填滿時(shí),鍵盤(pán)中斷處理程序會(huì)使IBM PC發(fā)出一聲響.鍵盤(pán)中斷處理程序做完這些事情之后,它就把控制權(quán)交還給原先被中斷的程序.如果有一個(gè)程序希望從鍵盤(pán)讀取一個(gè)字符時(shí),它就發(fā)出適當(dāng)?shù)能浖袛嘈盘?hào),這時(shí)候就由相對(duì)應(yīng)的中斷處理程序去檢查鍵盤(pán)隊(duì)列,并且傳回隊(duì)列中的第一個(gè)字符.
          上面所介紹的鍵盤(pán)輸入工作方式,在中斷驅(qū)動(dòng)系統(tǒng)中很普遍地采用.這和做法可以把實(shí)際上需要輸入的應(yīng)用程序和實(shí)際上執(zhí)行輸入的處理部分分開(kāi)來(lái).這種做法也可以用在其它不同形式的輸入和輸出外圍設(shè)備.
          3.3 改變輸入矢量
          中斷矢量?jī)?chǔ)存在IBM PC最前面的400H個(gè)字節(jié)中.每一個(gè)矢量的長(zhǎng)度是四個(gè)字節(jié)組成,這四個(gè)字節(jié)內(nèi)所存放的是中斷處理程序執(zhí)行的地址值.其中前兩個(gè)字節(jié)包含地址值的位移(Offset)部分,后面的兩個(gè)字節(jié)則包含了段(Segment)部分.
          中斷矢量有兩種修改方法.可以直接地設(shè)置中斷矢量的地址值,或是使用DOS所提供的系統(tǒng)調(diào)用設(shè)置中斷矢量的地址值.
          3.3.1 直接設(shè)置中斷矢量
          因?yàn)橹袛嗍噶恐皇谴娣诺刂分档拇鎯?chǔ)位置,因此我們可以直接地把地址存放到存儲(chǔ)位置中.以下是一個(gè)小例子:
          mov ax,0
          mov es,ax
          mov word ptr es:24,offset Keyboard
          mov word ptr es:26,seg Keyboard
          在許多情況下,上面的程序都可以正確地執(zhí)行.但是如果上面的程序正在執(zhí)行時(shí)突然敲下一個(gè)鍵的話,就可能會(huì)問(wèn)題;而最糟的情 況是發(fā)生:第三個(gè)MOV已經(jīng)執(zhí)行完畢,而第四個(gè)MOV尚未執(zhí)行時(shí).如果在此時(shí)敲下任何鍵的話,鍵盤(pán)中斷矢量都沒(méi)有任何意義,而造成整個(gè)系 統(tǒng)死機(jī).因此我們可以在設(shè)置中斷矢量時(shí),讓中斷無(wú)效,譬如:
          mov ax,0
          mov es,ax
          cli
          mov word ptr es:24,offset Keyboard
          mov word ptr es:26,seg Keyboard
          上面的做法在大部分的情況下都可以正確地執(zhí)行.但是CLI這個(gè)指令無(wú)法停止NMI中斷(不可屏蔽中斷),因此如果發(fā)生NMI中斷時(shí)就 沒(méi)用辦法.下面的這一種做法雖然比較復(fù)雜,但是對(duì)于所有的中斷都有效,這包括了NMI中斷在內(nèi):
          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 source 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是兩個(gè)字節(jié)(WORD)的指針(Pointer),其中包含了鍵盤(pán) 中斷處理程序的起始志趣值.REP這個(gè)指令將根據(jù)寄存 器CX所設(shè)置的次數(shù)來(lái)重復(fù)執(zhí)行MOVSW,而整個(gè)指令就如同單一的指令一樣.NMI中斷不能夠發(fā)生在一個(gè)完整的指令中.因?yàn)榈刂分蛋嵋频牟?作都能包含在一個(gè)單一指令中,因此可以免除任何中斷的干擾.
          3.3.2 使用DOS來(lái)設(shè)置中斷矢量
          因?yàn)橐氚踩卦O(shè)置中斷矢量需要一些技巧,因此DOS提供了一項(xiàng)特殊的服務(wù),以幫助程序人員安全地設(shè)置中斷矢量,如果只使用 DOS所提供的這項(xiàng)服務(wù)來(lái)設(shè)定中斷矢量的話,那么就不必?fù)?dān)心會(huì)發(fā)生前面所敘述的差錯(cuò).DOS同時(shí)也提供了:讀取中斷矢量的服務(wù).因?yàn)樽x 取中斷矢量的內(nèi)容不會(huì)修改系統(tǒng)的狀態(tài);因此若直接寫(xiě)程序讀取,也很安全.但是如果你要自己直接讀取中斷矢量的內(nèi)容時(shí),就必須計(jì)算 出中斷矢量的位置.而DOS已經(jīng)提供了這項(xiàng)服務(wù).
          使用DOS所提供的系統(tǒng)調(diào)用,來(lái)讀取中斷矢量的內(nèi)容時(shí),必須利用INT 21H中的函數(shù)35H(讀取中斷矢量),這個(gè)函數(shù)熱氣矢量號(hào)碼來(lái) 計(jì)算中斷矢量的地址,然后返回其中的內(nèi)容.以下就是一個(gè)例子:
          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來(lái)設(shè)置中斷矢量例子:
          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格式編程,可以建立一個(gè)BAT文件來(lái)處理寫(xiě)好的程序,以減少擊鍵次數(shù).設(shè)BAT文件名為MAKE.BAT:
          MASM %1
          LINK %1
          EXE2BIN %1.EXE %1.COM
          如果寫(xiě)好的程序名為MACRO.ASM,則可敲入:
          C:\MAKE MACRO.ASM
          即可.
          3.5 顯示中斷矢量
          下面這個(gè)例子可以列出所有的重要的中斷矢量?jī)?nèi)容,在剛剛打開(kāi)PC時(shí),并且沒(méi)有執(zhí)行任何駐留程序時(shí),可以發(fā)現(xiàn)所有的中斷矢量段值都相同,這些地址值所存放的是ROM的程序.當(dāng)你修改中斷矢量之后,就可以利用這個(gè)程序觀察到中斷矢量的變化.以下就是IVEC.ASM的內(nèi)容:
          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
          vloop:
          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 form of
          ;<banner>,<interrupt#>,<seg>:<offset>
          ;where <interrupt #>,<seg>and<offset>
          ;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 dbyte ;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 video 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 terminate
          dw v20
          db 10h ;Video driver
          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
          主站蜘蛛池模板: 沁阳市| 平和县| 北京市| 新巴尔虎右旗| 三门峡市| 紫云| 奈曼旗| 饶阳县| 昌平区| 油尖旺区| 新民市| 轮台县| 习水县| 寿光市| 衡水市| 梁平县| 杨浦区| 聂荣县| 建昌县| 临潭县| 上饶市| 西藏| 中牟县| 镇宁| 无棣县| 泾源县| 康平县| 高淳县| 广安市| 伊宁县| 运城市| 景谷| 天镇县| 阜平县| 准格尔旗| 新野县| 莱州市| 东城区| 阿克陶县| 阿合奇县| 通化县|