www.digitalmars.com         C & C++   DMDScript  

c++ - Interrupt Handling

reply Dan Guinter <dang2015 aol.com> writes:
I am looking to port an old C++ app from the (ancient)
Microsoft 16-bit DOS-capable C++ compiler.

Generally, it's going well, DMC being a little more
strict on some things than the older compiler.

What I'm wrestling with is interrupt handling.  The old
code used dos_getvect / setvect to insert my handler in
place of the clock handler, and this just doesn't work
under DMC - it crashes.

If I change over to use int_intercept, it works again.
Should the standard techniques of getvect/setvect be
expected to work? (all the good stuff like blocking
interrupts while changing vectors is in there, so this
isn't a newbie "How do I make interrupts go to my code"
question.

Now I'm battling packet driver interrupts since I make
int86 calls to tell the packet driver where my code is
(i.e., I can't [easily] use int_intercept because the
packet driver captures the actual interrupt then chains
out to my code).

I've narrowed the crash down to the actual interrupt that
occurs when a packet is received and the packet driver
tries to call my code.

Seems like this "ought" to work, but my battle with
setvect vs. int_intercept for the clock interrupt makes
me think that I have the same problem in my ethernet code.

Suggestions?  Thanks in advance for any pointers.

Dan
Sep 19 2010
parent reply Walter Bright <newshound2 digitalmars.com> writes:
Dan Guinter wrote:
 What I'm wrestling with is interrupt handling.  The old
 code used dos_getvect / setvect to insert my handler in
 place of the clock handler, and this just doesn't work
 under DMC - it crashes.

getvect and setvect should work. I don't know why it is failing for you. Do you have the source code for those two?
Sep 24 2010
next sibling parent reply Dan Guinter <dang2015 aol.com> writes:
I believe I found two problems;  I'll post them separately.

The first is that my old code had a typedef for the interrupt
handler, and under DMC it isn't handled the same way.

Here is the C code (compiled with -mld -4):

typedef void _interrupt IRQHANDLER;

IRQHANDLER irq( void ) {
    asm nop
    return;
}

void _interrupt irq2( void ) {
    asm nop
    return;
}

And here is the assembler.  You can see that the first form (the
typedef) ignored the _interrupt declaration and compiled as a
standard subroutine, not as an interrupt handler:

_irq    PROC NEAR
        nop
        retf
_irq    ENDP

_irq2   PROC NEAR
        pushaw
        push ds
        push es
        mov     bp, sp
        push ds
        mov     ax, DGROUP
        mov     ds, ax
        cld
        nop
        mov     sp, bp
        pop  es
        pop  ds
        popaw
        iret
_irq2   ENDP
Sep 27 2010
next sibling parent Walter Bright <newshound2 digitalmars.com> writes:
http://bugzilla.digitalmars.com/issues/show_bug.cgi?id=84
Oct 02 2010
prev sibling parent %u <kiran.nair gmail.com> writes:
Hello
Nov 06 2010
prev sibling parent reply Dan Guinter <dang2015 aol.com> writes:
The second thing I found involves accessing the registers in an
interrupt handler.  Since I've not seen anything mentioned in the
archives on this, I'm guessing it may be something in more recent
compiler releases (assuming what I found is valid).

Take the following C source where we try to access one of the
registers at the time of the interrupt:

void __interrupt isr( unsigned es, unsigned ds, unsigned di,
                      unsigned si, unsigned bp, unsigned sp,
                      unsigned bx, unsigned dx, unsigned cx,
                      unsigned ax, unsigned ip, unsigned cs,
                      unsigned flags ) {
    es = 0;

    return;
}

The resultant assembler (compiled with -mld -4):

_isr    PROC NEAR
        pushaw
        push ds
        push es
        mov     bp, sp
        push ds
        mov     ax, DGROUP
        mov     ds, ax
        cld
        mov     word ptr [bp+1AH], 0
        mov     sp, bp
        pop  es
        pop  ds
        popaw
        iret
_isr    ENDP

It appears that the compiler "skips over" the data on the stack
from the pusha, push ds, and push es, and offsets bp as if a
calling routine had actually pushed arguments onto the stack.

The line:
        mov     word ptr [bp+1AH], 0

Should be:
        mov     word ptr [bp+0], 0

I checked this against some old asm dumps from the Microsoft V1.52
compiler and the ES register is accessed at offset 0 from BP inside
the interrupt handler.

Under DMC, I patched around it by inserting an asm step to subtract
1AH from bp immediately upon entering (so the resultant mov is from
[bp+0]) and it worked (I had to add 1AH just before return to keep
SP correct).

Thanks!

Dan
Sep 27 2010
next sibling parent Walter Bright <newshound2 digitalmars.com> writes:
http://bugzilla.digitalmars.com/issues/show_bug.cgi?id=83
Oct 02 2010
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
Dan Guinter wrote:
 Thanks!

You're welcome. Thanks for the detailed reports, which I've added to bugzilla.
Oct 02 2010