rbono@necis.UUCP ( NM1D) (01/18/91)
Since I spent a bit of time looking for a work-around for this, I thought that I would share this with others, to same them some headaches.... I have found that the debugger built into Borland TurboC++ (1.0) is not very useful for debugging applications that contain a hardware Interrupt Service Routine (ISR).. This actually deals with the debugger built into TC++ and TD (2.0). I called Borland on this (talked with 'Dave' on the support line). They told me that I would have to live with this problem as it would require a major change to fix or provide a work around. They did state that TD-remote MAY not exhibit this problem, I havn't confirmed this. Problem: Can't single step, through 'background' code when a hardware interrupt service routine is part of the application. This is because Turbo 'swaps' the interrupt vectors on each breakpoint or single step. If a hardware interrupt that is supposed to be handled by your code occurs when the program is halted, the system may crash or hang (unpredictable results). This is because the interrupt vectors are not pointing to the proper ISR at the time of the interrupt. This is a big problem when trying to use IRQ0 through IRQ7. There is no currently known work-around (Borland confirmed this). Occurs in: TC++ 1.0, TC++ 1.01, TD 2.0, TD286, TD386 example: Design a *simple* terminal emulator. The terminal emulator contains code to handle the I/O to the COM port in an 'interrupt driven' fashion (i.e.: when a byte is received on COM1, IRQ4 is driven active, the ISR is responsible for placing the byte into a buffer. the buffer is read by the background task). The simple backgound code might look like this (this is a simplified example): main(void) { unsigned char inbyte; int key; InstallComHandler(); // Install the COM1 Interrupt Service Routine // this will take over the vector for IRQ4 while(1) // exit loop with proper keystroke { if(ComBufferHasData()) // if there is a byte in the buffer { inbyte = ReadComBuffer(); // read byte from buffer putch(inbyte); // display the byte } if(KeyPress()) // if a key has been pressed { key = ReadKey(); // read the key if(key == EXIT) // if user desires to exit the pgm { RemoveComHandler(); // remove the COM ISR exit(1); // exit the program } else { OutputToComPort(key); // Output keystroke to the COM port } } } } If you single step through this code, or set a breakpoint anywhere in this code and the COM port generates an interrupt, the interrupt will never be serviced if it occurs when the program is not executing. This will most-probably cause the ISR to stop functioning. This is due to the fact that the debugger restores the interrupt vectors as they were before the program was running, each time a breakpoint occurs (and during single stepping). You can place one breakpoint into your code and follow execution from that point. But if another interrupt occurs during your single stepping, or during the time the Debugger has control, your application may never 'see' the interrupt or may hang or crash the system. This 'feature' of the debugger is explained in a paragraph in the Turbo Debugger manual. It states that the debugger maintains three sets of interrupt vectors (vectors 00 - 0x2F). The first copy is made before the debugger is started. This set is restored when exiting back to DOS and when shelling out to DOS. The second set is the Debugger's own copy of the vectors. THESE ARE IN EFFECT WHENEVER THE DEBUGGER IS RUNNING OR ON THE SCREEN (emphasis is mine). The third set is those of the program that you are debugging. These vectors are RESTORED EVERY TIME YOU RUN OR STEP your program, and are saved each time you stop your program (by single stepping, or break- point). The problem is that when debugging applications that make use of external hardware interrupts, the debugger actually 'gets in the way' and will not allow these interrupts to be serviced by your ISR (Interrupt Service Routine). I have found NO WORKAROUND for this. If anyone does, please let me know. This makes the Borland package almost useless (in my opinion) for debugging software that makes use of hardware interrupts (i.e.: IRQ0-IRQ7). This should not affect software that makes use of software interrupts (INT X instructions). It would be nice if Borland provided an option that allowed a specified vector (or vectors) to remain in place during the debugging of an application. They could then restore the vectors when exiting the debugger or shelling out to DOS. I thought that since this consumed a day of my time looking for a workaround, that I would let other know about this limitation. If someone does have a workaround. Please inform me. This occured with TC++ 1.0 (I assume with 1.01 also) and with TD 2.0 (includes TD386 and TD286). -- /**************************************************************************\ * Rich Bono (NM1D) Note NEW email address: rbono@necis.ma.nec.com * * (508) 635-6300 NEC Technologies Inc. NM1D@WB1DSW * \**************************************************************************/ -- /**************************************************************************\ * Rich Bono (NM1D) Note NEW email address: rbono@necis.ma.nec.com * * (508) 635-6300 NEC Technologies Inc. NM1D@WB1DSW * \**************************************************************************/
williams@umaxc.weeg.uiowa.edu (Kent Williams) (01/19/91)
EVEN WORSE. I have a VIP 386SX system, and a microsoft serial mouse on COM1. When I use td386, the mouse works fine in the debugger. If I move the mouse while my application is running, I get popped back into TD with an exception 6 error (Invalid opcode) -- Kent Williams --- williams@umaxc.weeg.uiowa.edu "'Is this heaven?' --- 'No, this is Iowa'" - from the movie "Field of Dreams" "This isn't heaven, ... this is Cleveland" - Harry Allard, in "The Stupids Die"