Thread overview
Interrupt Handling
Sep 19, 2010
Dan Guinter
Sep 25, 2010
Walter Bright
Sep 28, 2010
Dan Guinter
Oct 02, 2010
Walter Bright
Nov 06, 2010
%u
Sep 28, 2010
Dan Guinter
Oct 02, 2010
Walter Bright
Oct 02, 2010
Walter Bright
September 19, 2010
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
September 25, 2010
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?
September 28, 2010
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
September 28, 2010
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
October 02, 2010
http://bugzilla.digitalmars.com/issues/show_bug.cgi?id=83
October 02, 2010
http://bugzilla.digitalmars.com/issues/show_bug.cgi?id=84
October 02, 2010
Dan Guinter wrote:
> Thanks!

You're welcome. Thanks for the detailed reports, which I've added to bugzilla.
November 06, 2010
Hello