TIP: Click on subject to list as thread! ANSI
echo: power_bas
to: ALL
from: BRIAN MCLAUGHLIN
date: 1996-03-17 02:42:00
subject: DEMO of ISR code in P 1/2

For those who might be interested, here is a code skeleton that
demonstrates some of the techniques required for writing an ISR that
hooks into the interrupt chain for Int 21h, does some handling, then
passes control to the next interrupt handler in the chain - all in
PowerBASIC, using inline ASM.
'----------------------------------------------------------------------
' ISRDEMO.BAS   -  demonstrates how to write an ISR that traps Int 21h
'                  then chains to the old Int 21h interrupt afterward.
'
' This demo calls a SUB that resets the Interrupt vector table to point
' to a new interrupt handler written in inline ASM code. This ISR
' looks at every call to Int 21h.
'
' If the Int 21h call is for service 3Bh (the set directory service) the
' handler calls the BIOS to print the new directory being set. (You can't
' call PB's PRINT statement or a DOS service to do the printing.) After
' the ISR finishes, it chains to the old Int 21h handler.
'
' Once the new ISR is in place, the demo program shells. As long as you
' are in the shell, the ISR is operational. As soon as you leave the shell
' the demo removes the ISR and restores Int 21h as it was before.
'________________________________________________________________________
$LIB ALL OFF
DECLARE SUB SetInt21InterruptVector ()
DECLARE SUB RestoreInt21InterruptVector ()
DIM Old21Segment AS SHARED WORD
DIM Old21Offset AS SHARED WORD
'================  START OF MAIN CODE ====================
SetInt21InterruptVector
SHELL
RestoreInt21InterruptVector
END
'================  END OF MAIN CODE ====================
'================================
 SUB SetInt21InterruptVector ()
'================================
HandlerSegment?? = CODESEG(DOSHandler)
HandlerOffset?? = CODEPTR(DOSHandler)
ASM  Push DS
ASM  Push ES
ASM  Push AX
ASM  Push BX
ASM  Mov AX, &H3521            ; get vector for DOS interrupt &H21
ASM  Int &H21
ASM  Mov Old21Address[0], BX   ; put the old 3B vector address in ISR
ASM  Mov Old21Offset, BX       ; save it in the global variable, too
ASM  Mov BX, ES
ASM  Mov Old21Address[2], BX   ; put into the ISR
ASM  Mov Old21Segment, BX      ; save it in the global variable, too
ASM  Mov DX, HandlerOffset??   ; point DS:DX at new handler
ASM  Mov AX, HandlerSegment??
ASM  Mov DS, AX
ASM  Mov AX, &H2521         ; set new vector for DOS interrupt &H21
ASM  Int &H21               ; now the table points to our ISR code
ASM  Pop BX
ASM  Pop AX
ASM  Pop ES
ASM  Pop DS
EXIT SUB
' The following ISR code is called any time DOS is called
DOSHandler:
ASM  PushF           ; we must save what we might trash!
ASM  Push BP
ASM  Push ES
ASM  Push DS
ASM  Push AX
ASM  Cmp AH, &H3B    ; is "set dir" service being requested?
ASM  Je  SetDirRequested  ; if so, go handle it
ASM  Pop AX          ; otherwise, pop everything we pushed
ASM  Pop DS
ASM  Pop ES
ASM  Pop BP
ASM  PopF            ; and prepare to chain to old int 21h code
Chain2OldInt:
ASM  DB &H0EA        ; this opcode for JMP FAR is treated as code, not data
Old21Address:
ASM   DD  0          ; chain to the old Int 21h address
SetDirRequested:     ; here we intervene whenever 3Bh is called
ASM  Push DX         ; save everything we might trash!
ASM  Push CX
ASM  Push BX
ASM  Push DI
ASM  Push SI
'here is where the meat of the ISR code goes:
GOSUB BiosPrint     ' in this case, it's just one GOSUB
ASM  Pop SI         ; pop everything that was pushed
ASM  Pop DI
ASM  Pop BX
ASM  Pop CX
ASM  Pop DX
ASM  Pop AX
ASM  Pop DS
ASM  Pop ES
ASM  Pop BP
ASM  PopF
ASM  Jmp Chain2OldInt
'---------------  END OF MAIN ISR CODE  -------------------
' We GOSUB to BiosPrint from inside the ISR. The Pushes at the start are
' redundant -- these same registers have alreay been pushed in the ISR.
' They are inserted here just for the sake of showing "good form".
BiosPrint:
ASM  Push AX         ; we arrive here with DS:DX pointing to the name
ASM  Push BX         ; of the directory that will be set by DOS
ASM  Push CX
ASM  Push SI
ASM  Mov AH, &H0E    ; ask for BIOS service 0Eh - teletype printing
ASM  Mov BH, 0       ; assumes screen page zero is active
ASM  Mov SI, DX      ; set DS:SI to the same as DS:DX
Loop1:
ASM  Mov CX, 1       ; this loop prints each char until the the null char
ASM  Lodsb           ; loads one char from DS:SI into AL
ASM  Or AL, AL       ; see if it is the terminal null char
ASM  Jz ExitLoop1    ; if it is, stop the loop
ASM  Int &H10        ; call BIOS interrupt 10h, for service 0Eh
ASM  Jmp Loop1
>>> Continued to next message
 * SLMR 2.1a * MAXLIB For PB v1.2 - Access arrays and files in EMS/XMS!
--- WILDMAIL!/WC v4.12 
---------------
* Origin: Com-Dat BBS - Hillsboro, OR. HST DS (1:105/314.0)

SOURCE: echomail via exec-pc

Email questions or comments to sysop@ipingthereforeiam.com
All parts of this website painstakingly hand-crafted in the U.S.A.!
IPTIA BBS/MUD/Terminal/Game Server List, © 2025 IPTIA Consulting™.