用汇编编写DOS下的内存驻留程序(3) (转)

用汇编编写DOS下的内存驻留程序(3) (转)[@more@] 三 中断矢量
3.1 IBM PC提供的中断
 IBM PC有两种基本形态的中断.如果是由外围设备所产生的中断就叫做 硬件中断(Hardware interrupt),譬如:键盘, 磁盘机和时钟等外围设备都可以产生硬件中断.外围设备所产生的中断信号都连接到中断控制器,中断控制器可以根据它们之间的重要性来安排优先顺序,以便使 cpu有效地处理这些硬件信号.另一种中断是 软件中断(Software interrupt),软件中断也叫做陷井(Trap),它是由 执行中的软件所产生.虽然软件包中断的处理方式和硬件中断完全相同,但是通常软件中断是希望执行操作 系统所提供的服务.
 表3.1是IBM PC所提供的中断,这些中断是根据中断号码和中断矢量(Interrupt vector)排列.
 IBM PC的 用户或是编写应用 程序的程序人员很少会直接接触到硬件中断,除非是使用某些特殊的硬件,或是需要较严格的要求时,最常被修改的硬件中断是敲键盘所产生的中断(9H),尤其是文本编辑的程序.大体而言,只有硬件设计者基是系统程序人员才会注意到所有在硬件中断;编写 内存驻留程序的设计人员则只使用到部分硬件中断而已,尤其是:键盘中断和计时器(Timer)的中断.
 反之,软件中断对于任何编写汇 编程序的人,甚至对编写高级语言程序的人都相当的重要.软件中断是应用程序进入到IBM PC 操作系统的接口,经由这些接口应用程序才可以执行所要求的系统服务.
 其中软件中断中最重要,同时也是最常被 汇编语言 程序设计师所用到是D os INT 21H.这个中断是执行DOS系统 调用的软件中断,它可以让应用程序执行任何DOS的操作.
 接下来最有用的软件中断是ROM- BIOS(基本输入输出系统)所提供的中断.这些软件中断是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  word 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 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是两个字节(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 oop
 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 fo RM of
 ;,,:
 ;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  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 v ideo 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 te Rminate
 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

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/10752019/viewspace-958645/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/10752019/viewspace-958645/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值