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.
seanna@bnr.ca (Seanna Watson) (05/29/91)
A quick note while on the topic: I discovered tody (after some effort) that in TC++, interrupt handlers take arguments (...) not (void), as in TC. It's NOT documented. /Steve Watson
barry@gpu.utcs.utoronto.ca (Barry Lay) (05/30/91)
MSC appears to have the interrupt keyword for functions as well, and will take the various register values as parameters. I would like to know if this is the way to deal with the "hooks" that you can set up with INT 33h (function 14h, or thereabouts). That is, can I set up a function which will be called if, say, mouse button one is pressed. My understanding of the interrupt keyword is that a special prologue and epilogue is created which saves all of the registers (and restores them) and uses IRET rather than RET to return. What I don't know is what the mouse driver expects the user interrupt routine to do. Barry
Ralf.Brown@B.GP.CS.CMU.EDU (05/30/91)
In article <1991May29.044612.8057@bnr.ca>, seanna@bnr.ca (Seanna Watson) wrote: }A quick note while on the topic: I discovered tody (after some effort) that }in TC++, interrupt handlers take arguments (...) not (void), as in TC. }It's NOT documented. Sure it is. See page 388 of the TC2 User's Guide. Interrupt functions have never had void arguments, although you might have been fooled by the lack of argument declarations in the prototype for getvect() and setvect(). But foo() is *not* the same as foo(void). -- {backbone}!cs.cmu.edu!ralf ARPA: RALF@CS.CMU.EDU FIDO: Ralf Brown 1:129/53 BITnet: RALF%CS.CMU.EDU@CARNEGIE AT&Tnet: (412)268-3053 (school) FAX: ask DISCLAIMER? Did | It isn't what we don't know that gives us trouble, it's I claim something?| what we know that ain't so. --Will Rogers
nfs@elan.Princeton.EDU (Norbert Schlenker) (05/31/91)
In article <334@nazgul.UUCP> bright@nazgul.UUCP (Walter Bright) writes: >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. Kudos to Zortech for this. ZTC's interrupt package is without a doubt the right way to handle the entire question, unlike the Turbo interrupt kludge which Microsoft unfortunately picked up (it amazes me that manufacturers striving for ANSI compatibility would install such an amazing mess at the same time they are fixing up old kludges by turning far into _far, etc.) Zortech's method is altogether incredibly clever. BUT... Zortech has yet to ship a working copy of their int_intercept routine. A caller that asks int_intercept() to use the normal stack will find that all works well until int_restore() is called, at which point the heap checker thinks the heap has been trashed. I thought I had a wild pointer somewhere and spent days looking for this. This problem was reported way back around v2.11 of the library and still exists in the currently shipping v2.18. There is a good version on the Zortech BBS. Let's hope v3.00 is better. Norbert
jgb@prism.gatech.EDU (James G. Baker) (06/04/91)
In article <1991May29.044612.8057@bnr.ca> seanna@bnr.ca (Seanna Watson) writes: >A quick note while on the topic: I discovered tody (after some effort) that >in TC++, interrupt handlers take arguments (...) not (void), as in TC. >It's NOT documented. Neat trick. :-) How does one pass arguments to an ISR? I would not think anything would be passed, unless you consider the registers "passed" to it. -- BAKER,JAMES G - Undergraduate Lab Instructor, School of Electrical Engineering ____ _ _ Georgia Institute of Technology, Atlanta Georgia, 30332 | | _ |_) uucp: ...!{decvax,hplabs,ncar,purdue,rutgers}!gatech!prism!jgb (_|. |_). |_). Internet: jgb@prism.gatech.edu, jgb@ee, jgb@eecom, jgb@cc
pgt@hpfcso.FC.HP.COM (Paul Tobin) (06/06/91)
* Neat trick. :-) * How does one pass arguments to an ISR? I would not think anything would * be passed, unless you consider the registers "passed" to it. I suppose TC++ could actually catch the interrupt and generate a call frame for your ISR, eh (what stack is in use at that time)? I wonder what good that would do, though? It could pass in global variables, but the ISR could get at those itself. Can anyone think of any other ideas? Paul "my life is constantly interrupted" Tobin pgt@hpfcla.fc.hp.com
resnicks@netcom.COM (Steve Resnick) (06/08/91)
In article <15590004@hpfcso.FC.HP.COM> pgt@hpfcso.FC.HP.COM (Paul Tobin) writes: >* Neat trick. :-) >* How does one pass arguments to an ISR? I would not think anything would >* be passed, unless you consider the registers "passed" to it. > >I suppose TC++ could actually catch the interrupt and generate a call >frame for your ISR, eh (what stack is in use at that time)? I wonder >what good that would do, though? It could pass in global variables, >but the ISR could get at those itself. Can anyone think of any other >ideas? In the Asynch driver I wrote, I have default ISR's for 4 comm ports. These ISR's look like: void interrupt IsrCOM1(void) { IsrHandler(0); } void interrupt IsrCOM2(void) { IsrHandler(1); } . . . void IsrHandler(int PortID) { . . . [Handle the interrupt and return] } This allows me to have one real ISR which gets called by the dummy ISR's identifying which UART needs serivce, rather than duplicating code for each serial port. The routine, IsrHandler(), is re-entrant, meaning that it doesn't modify global variables, nor does it have any static variables. Hope this helps... Steve -- ------------------------------------------------------------------------------- resnicks@netcom.com, steve@camphq, IFNA: 1:143/105.0, co moderator for comp.binaries.os2 Real life: Steve Resnick. Chief Software Architect, Process Scientific, Inc Flames, grammar and spelling errors >/dev/null The Asylum OS/2 BBS - (408)263-8017 12/2400,8,1 - Running Maximus CBCS 1.2 -------------------------------------------------------------------------------