Search the FAQ Archives

3 - A - B - C - D - E - F - G - H - I - J - K - L - M
N - O - P - Q - R - S - T - U - V - W - X - Y - Z
faqs.org - Internet FAQ Archives

comp.os.msdos.programmer FAQ part 4/5
Section - - Why does my interrupt function behave strangely?

( Part1 - Part2 - Part3 - Part4 - Part5 - Single Page )
[ Usenet FAQs | Web FAQs | Documents | RFC Index | Sex offenders ]


Top Document: comp.os.msdos.programmer FAQ part 4/5
Previous Document: - How can I write a TSR (terminate-stay-resident utility)?
Next Document: - How can I write a device driver?
See reader questions & answers on this topic! - Help others by sharing your knowledge

 Interrupt service routines can be tricky, because you have to do some
 things differently from "normal" programs. If you make a mistake,
 debugging is a pain because the symptoms may not point at what's wrong.
 Your machine may lock up or behave erratically, or just about anything
 else can happen. Here are some things to look for. (See <Q:08.06> [How
 can I write a TSR (terminate-stay-resident utility)?] for general
 techniques that may prevent a problem.)

 First, did you fail to set up the registers at the start of your
 routine? When your routine begins executing, you can count on having CS
 point to your code segment and SS:SP point to some valid stack (of
 unknown length), and that's it. In particular, an interrupt service
 routine must set DS to DGROUP before accessing any data in its data
 segments. (If you're writing in a high-level language, the compiler may
 generate this code for you automatically; check your compiler manual.
 For instance, in Borland and Microsoft C, give your function the
 "interrupt" attribute.)

 Did you remember to turn off stack checking when compiling your
 interrupt server and any functions it calls? The stack during the
 interrupt is not where the stack-checking code expects it to be.
 (Caution: Some third-party libraries have stack checking compiled in, so
 you can't call them from your interrupt service routine.)

 Next, are you calling any DOS functions (INT 21, 25, or 26) in your
 routine? DOS is not re-entrant. This means that if your interrupt
 happens to be triggered while the CPU is executing a DOS function,
 calling another DOS function will wreak havoc. (Some DOS functions are
 fully re-entrant, as noted in Ralf Brown's interrupt list (<Q:02.03>
 [What and where is Ralf Brown's interrupt list?]). Also, your program
 can test, in a way too complicated to present here, when it's safe to
 call non-re-entrant DOS functions. See INT 28, INT 21 AH=34, and INT 21
 AX=5D06 or 5D0B; and consult {Undocumented DOS} by Andrew Schulman. Your
 program must read both the "InDOS flag" and the "critical error flag".)

 Is a function in your language library causing trouble? Does it depend
 on some initializations done at program startup that is no longer
 available when the interrupt executes? Does it call DOS (see preceding
 paragraph)? For example, in both Borland and Microsoft C the memory-
 allocation functions (malloc(), etc..) call DOS functions and also
 depend on setups that they can't get at from inside an interrupt; so do
 the standard I/O functions like scanf() and printf(). Many other library
 functions have the same problem, so you can't use them inside an
 interrupt function without special precautions.

 Is your routine simply taking too long? This can be a problem if you're
 hooking on to the timer interrupt, INT 1C or INT 8. That interrupt
 expects to be called about every 55 ms, which is 18.2 times a second.
 Therefore your routine, plus any others hooked to the same interrupts,
 must execute in less than 55 ms. If they use even a substantial fraction
 of that time, you'll see significant slowdowns of your foreground
 program. A good discussion is downloadable as:
 <http://www.simtel.net/pub/pd/46893.html>

 Did you forget to restore all registers at the end of your routine?

 Reader, Morten Welinder, notes that programmers of interrupt procedures
 in Borland/Turbo Pascal 7.0 should be aware that the high words or the
 32-bit registers are not saved automatically and that the run-time
 library may trash them if, e.g., you use longint operations. The easy
 way around this is to do "Test8086 := 0;" before installing the
 interrupt handler.

 Did you chain improperly to the original interrupt? You need to restore
 the stack to the way it was upon entry to your routine, then do a far
 jump (not call) to the original interrupt service routine.

 (The process is a little different in high-level languages.)

User Contributions:

Comment about this article, ask questions, or add new information about this topic:

CAPTCHA




Top Document: comp.os.msdos.programmer FAQ part 4/5
Previous Document: - How can I write a TSR (terminate-stay-resident utility)?
Next Document: - How can I write a device driver?

Part1 - Part2 - Part3 - Part4 - Part5 - Single Page

[ Usenet FAQs | Web FAQs | Documents | RFC Index ]

Send corrections/additions to the FAQ Maintainer:
jeffrey@carlyle.org (Jeffrey Carlyle)





Last Update March 27 2014 @ 02:11 PM