Path: utzoo!utgpu!watmath!att!dptg!rutgers!apple!brutus.cs.uiuc.edu!wuarchive!wugate!uunet!philmtl!philabs!ttidca!quad1!few From: few@quad1.quad.com (Frank Whaley) Newsgroups: comp.lang.c Subject: Re: TSR's with TC Message-ID: <2539@gouda.quad.com> Date: 29 Aug 89 23:56:25 GMT References: <3723@ncsuvx.ncsu.edu> <69@tor.nhh.no> <1098@koko.CSUStan.EDU> Reply-To: few@gouda.quad.com (Frank Whaley) Organization: Quadratron Systems, Westlake Village, CA Lines: 116 In article <1098@koko.CSUStan.EDU> jb@koko.UUCP (John Birchfield) writes: >In article <3723@ncsuvx.ncsu.edu>, sherman@csclea.ncsu.edu (Chris Sherman) writes: >> _chain_intr, which is usually used in an interrupt handler, accepts the >> address of another interrupt handler, and jumps (not calls) over to it. >> It is as if the first handler was never called. >> >Turbo C allows writing interrupt handlers directly in C using >pretty much the same mechanism as Microsoft. The following C >program is provided as a very succinct example. << succinct example deleted >> While Turbo C does provide excellent interrupt handling support, the _chain_intr() function provides one capability not available from the normal Turbo C facilities: The ability to preserve original register contents when passing control to a subsequent (or original, depending on your point of view) interrupt handler. Note that the correct synopsis of an interrupt handling function is: void interrupt handler(bp,di,si,ds,es,dx,cx,bx,ax,ip,cs,fl) int bp,di,si,ds,es,dx,cx,bx,ax,ip,cs,fl; as the register contents are pushed upon entry, and popped upon exit. While within the handler, DS contains the current DGROUP value and other registers change as necessary. If the original interrupt handler is called from within our handler, it is unlikely that the correct register values will be passed. For many interrupt service routines this is inconsequential, as they do not care what the previous state of the machine was -- for example, serial port interrupt handlers are responding to a hardware interrupt and must preserve and restore the machine state at the time of the interrupt. However, when software interrupts are used for communication between processes (I use the term loosely :-), the contents of the registers is very important. The DOS Services interrupt (0x21) and the Multiplex interrupt (0x2f) are two examples that expect parameters to be provided in registers which are modified by the Turbo C interrupt service code. Fortunately (this is the part you were waiting for) the _chain_intr() function is not dificult to implement. Attached is a "dirty" version (values are popped into code-segment variables) which is missing the necessary segment/group descriptions, but which demonstrates the principles of chaining interrupts. I should note that, if desired, interrupt handlers can examine or modify the input register values. For example, to count all "open file" calls within a program: Assuming: ... long opencount = 0; void interrupt (*old21)(); ... old21 = getvect(0x21); setvect(0x21, my21); ... void interrupt my21(bp,di,si,ds,es,dx,cx,bx,ax) int bp,di,si,ds,es,dx,cx,bx,ax; { if ( (ax & 0xff00) == 0x3d00 ) opencount++; _chain_intr(old21); } ----- ;-----------------------------------------------------------------------| ; _chain_intr -- chain interrupt | ; | ; SYNOPSIS | ; void _chain_intr(target) | ; void interrupt (*target)(); | ; | ; DESCRIPTION | ; Chain to another interrupt handler, passing original | ; (or possibly modified) register values. | ; | ; RETURNS | ; This function returns to the original source of the | ; interrupt. | ; | ;-----------------------------------------------------------------------| Public __chain_intr __chain_intr Proc Near POP AX ; clear return addr ;;;;;;; POP AX ; another for large code models POP Word Ptr CS:target ; get target addr into jump POP Word Ptr CS:target + 2 POP BP ; restore saved registers POP DI POP SI POP DS POP ES POP DX POP CX POP BX POP AX ; we leave original IP, CS and flags on stack DB 0EAH ; JMPF target DD 0 ; target address __chain_intr EndP ----- -- Frank Whaley Senior Development Engineer Quadratron Systems Incorporated few@quad1.quad.com uunet!ccicpg!quad1!few Water separates the people of the world; Wine unites them.