[alt.msdos.programmer] Handling interrupts in C

bright@nazgul.UUCP (Walter Bright) (05/28/91)

In article <1991May21.140557.16018@cbnewsc.att.com> tjr@cbnewsc.att.com (thomas.j.roberts) writes:
/From article <1991May20.171545.23591@amc.com>, by jwbirdsa@amc.com (James Birdsall):
/>    Anyone writing interrupt handlers using TC++'s "interrupt" keyword
/> should be aware that DS is not preserved into the function. DS is preserved
/> through the function; the value of DS after the interrupt is the same as
/> before. However, the value of DS while the function is executing is not the
/> same as the value when it was called. The entry code pushes all the
/> registers on the stack and then reloads DS with the value for the program's
/> near data segment.
/Note that unlike normal C functions, modifying the parameters to an
/interrupt function within the function will change the values of registers
/used by the caller upon its return - great care is needed! READ THE MANUAL! 
/The truly hard thing to do is to chain to the previous interrupt handler
/with the caller's registers, and arrange for the previous handler to
/return registers to the caller (this is usually what you want to do
/when "wrapping" int 21H, et al). Borland did not include an appropriate
/function in the library (I believe it would really need to be a
/"psuedo-function", as its semantics could not be those of a normal
/C function). Thus, to do this you must use assembly language to
/restore the stack and registers and then jump to the previous
/handler's address (without modifying ANY registers!).

The way Zortech supports interrupts is via a library package. You can
set up a normal C function as an interrupt service routine. Into that
service routine is passed a pointer to the register state at the time
of the interrupt. The registers can thus be examined and modified.
Within the interrupt routine, you can call the previous interrupt handler
via another call to a library function. Upon return from the handler, you
can choose to return from the interrupt or chain to the previous handler,
by having a 0 or non-0 return value.

The interrupt service routine can be set up to be called with its own local
stack, or use the caller's.

The nice thing about this package is it requires no extensions to the compiler,
and the implementation of the library package has been done for DOS, Rational's
286 DOS Extender, and Pharlap's DOS Extender. We will soon have a version
for Windows 3 too. No source code changes are required.

The disadvantage of using this package is it has a little longer interrupt
latency. I'd argue, though, that if you need every watt out of your ISR then
you need to write it in assembly anyway. I've written numerous things with this,
including mouse serial drivers, control-break handlers, and int 21h filters.

Hooking ^C (interrupt x23) to call myhandler() is as simple as:

	int_intercept(0x23,myhandler,0);

and unhooking it is:

	int_restore(0x23);

If you use the package you are not wedded to Zortech, either, unlike if you
use special compiler extensions. The library source is included, and is
trivially convertible to Borland or Microsoft C.