----------------------------------------------------------------------------
The first part is the interrupt service routine itself. It doesn't do anything very exciting; just loads a value into dx, and then returns.
----------------------------------------------------------------------------
.model tiny
.186
org 100h
start: jmp short InstallIt
;*******************************************************************
;;;; our interrupt code and data goes here
.algnw ; lets align it on the next word boundary
OurStart: cli
push ds ; save data seg
push cs ; point ds to cs
pop ds
or ah,ah ; if ah = 0 then service 0
je short Service0
cmp ah,01 ; if ah = 1 then service 1
je short Service1
cmp ah,02 ; if ah = 2 then service 2
je short Service2
JustExit: pop ds ; else just return
sti
iret
; our service #0 (ah = 00h)
Service0: mov dx,00h ; do something simple for example
jmp short JustExit
; our service #1 (ah = 01h)
Service1: mov dx,01h ; do something simple for example
jmp short JustExit
; our service #2 (ah = 02h)
Service2: mov dx,02h ; do something simple for example
jmp short JustExit
; other services go here
OurEnd:
;;;; end of our interrupt code and data
;*******************************************************************
-------------------------------------------------------------------------------
The rest of the program ist the installation procedure
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
Prints one of the messages at the bottom
-------------------------------------------------------------------------------
InstallIt: mov si,offset StartIt ; display start up string
call prtstring ;
-------------------------------------------------------------------------------
point es:bx at the interrupt vector table
-------------------------------------------------------------------------------
xor bx,bx ; make es:bx point to 0000:00D0h
mov es,bx ;
mov bx,00D0h ;
-------------------------------------------------------------------------------
load cx with max number of entries you want to examine
-------------------------------------------------------------------------------
mov cx,204 ; 256 interrupts (00-FF)(-34h)
-------------------------------------------------------------------------------
look at the entries one at a time
-------------------------------------------------------------------------------
MainLoop:
-------------------------------------------------------------------------------
load ax:si with address of isr
-------------------------------------------------------------------------------
mov si,es:[bx] ; get interrupt vector address
inc bx ; offset first (little endian)
inc bx ;
mov ax,es:[bx] ; segment second (little endian)
------------------------------------------------------------------------------
point es:bx at next entry in table
-----------------------------------------------------------------------------
inc bx ;
inc bx ;
------------------------------------------------------------------------------
Does ax:si point to read only memory in the BIOS?
-----------------------------------------------------------------------------
cmp ax,0F000h ; if segment => F000h then in ROM-BIOS
jae short NotIRET ; (if in BIOS then skip it)
-----------------------------------------------------------------------------
does routine pointed to by ax:si consist of nothing more than an iret
instruction (i.e. - available for use)?
-----------------------------------------------------------------------------
push es ;
mov es,ax ; see if IRET
mov dl,es:[si] ;
pop es ;
cmp dl,0CFh ; is it IRET
------------------------------------------------------------------------------
if available for use jump out of loop; otherwise go round loop,
and look at next entry in interrupt vector table
------------------------------------------------------------------------------
je short FndOne ; if so, then not used
NotIRET: inc byte CIntVNum ; inc for next time
loop MainLoop ;
-------------------------------------------------------------------------------
Gone round loop max number of times, and still haven't found free
entry in vector table? Then print error message and exit.
CIntVNum now contains number of free interrupt.
-------------------------------------------------------------------------------
mov si,offset NoFndOneS ; didn't find one
call prtstring
jmp short DoneErr
------------------------------------------------------------------------------
Print message telling of the glad tidings that you have found a free entry
------------------------------------------------------------------------------
FndOne:
mov si,offset FndOneS
call prtstring
------------------------------------------------------------------------------
at the moment bx points to next entry after the free one. load ax with that offset, and then move it back 4 bytes so it points to free entry
Then print the offset of free entry
------------------------------------------------------------------------------
mov ax,bx
sub ax,04 ; backup to first of vector
call prthex
------------------------------------------------------------------------------
Point si at first part of message and then print it
------------------------------------------------------------------------------
mov si,offset IntNumS
call prtstring
-------------------------------------------------------------------------
Load al with free int number & print second part of message
------------------------------------------------------------------------
mov al,CIntVNum ; display current int number
call prthexs ;
mov dl,'h' ; print 'h'
mov ah,02 ;
int 21h ;
push cs
pop ds
------------------------------------------------------------------------
Load interrupt table with address of your isr
------------------------------------------------------------------------
mov al,CIntVNum ; vector to change
mov ah,25h
mov dx,offset cs:OurStart
int 21h
------------------------------------------------------------------------
Don't need memory allocated for environment strings when
prog was loaded - so free it
-----------------------------------------------------------------------
mov ah,62h ; get and free environment block
int 21h ;
mov es,bx ;
mov ax,es:[2Ch] ;
mov es,ax ;
mov ah,49h ;
int 21h ;
-------------------------------------------------------------------------
Calculate amount of memory needed for resident part of program
including the program segment prefix
Then terminate and stay resident
-------------------------------------------------------------------------
mov dx,offset cs:OurEnd ; offset of end of our code
shr dx,04 ; div by 16 (make it a paragraph #)
inc dx ; just in case
add dx,16 ; The PSP
mov ax,3100h ; service number and RC = 0
int 21h ; TSR service
---------------------------------------------------------------------------
Error occurred, so terminate without staying resident
---------------------------------------------------------------------------
DoneErr:
mov ah,4Ch ; exit to DOS (no TSR)
int 21h ;
prtstring proc near
uses ax dx si
-------------------------------------------------------------------------
load next character then increment si so that it points to
following character
-------------------------------------------------------------------------
ps1:
mov dl,[si] ; Get character
inc si ; Point to next one
------------------------------------------------------------------------
strings used by this routine are null terminated, so test for null byte.
or dl,dl is equivalent to cmp dl, 0
if it is end of string jump out of loop
------------------------------------------------------------------------
or dl,dl ; End of string?
jz short ps2 ; Yes, so exit
mov ah,02h ; Output a character
int 21h
jmp short ps1 ; Keep doing it
ps2:
ret
prtstring endp
PrtHexs proc near uses ax bx dx cx
--------------------------------------------------------------------------
point ds:bx at array of hex digits
--------------------------------------------------------------------------
mov bx,offset Hex
push ax
---------------------------------------------------------------------------
procedure called with 8 bit hex number (say 4Dh). shr to get upper four bits into lowere for bits (ie 4 in this example).
al now contains index into string of hex digits
---------------------------------------------------------------------------
shr al,04h
---------------------------------------------------------------------------
load digit from string into al, and print it
--------------------------------------------------------------------------
xlatb
mov dl,al
mov ah,02
int 21h
pop ax
--------------------------------------------------------------------------
now isolate lower four bits, and then repeat all of the above
--------------------------------------------------------------------------
and al,0Fh
xlatb
mov dl,al
mov ah,02
int 21h
ret
PrtHexs endp
-------------------------------------------------------------------------------
I'll leave you to figure this one out for yourself
-------------------------------------------------------------------------------
PrtHex proc near uses ax bx cx dx
mov bx,offset Hex
mov cx,04h
HexLoop: push ax
mov al,ah
shr al,04h
xlatb
mov dl,al
mov ah,02
int 21h
pop ax
shl ax,04h
loop HexLoop
ret
PrtHex endp
----------------------------------------------------------------------------
int the strings below:
10 = ascii code for carriage return
13 = ascii code for line feed
-----------------------------------------------------------------------------
CIntVNum db 34h ; starting with int 34h
StartIt db 13,10,'Interrupt Install Util Version 01.00b'
db 13,10,'Forever Young Software(r) (C)opyright 1984-2000',13,10
db 13,10,' Finding unused Interrupt vector number... (starting with 34h)',13,10,0
NoFndOneS db 13,10,"****Didn't find an unused interrupt vector number***"
FndOneS db 13,10,' Found an unused interrupt at: 0000:',0
IntNumS db 13,10,' Interrupt number: ',0
Hex db '0123456789ABCDEF'
.end start[/quote]