Mail Archives: djgpp/1996/07/23/10:37:58
Hi,
  I wrote the following code a while ago part of a 16.16 fixed point
library.  The idea was to catch a division the processor couldn't handle
eg. divide by zero, and return a (random) result without causing an
exception.
This following code works fine under DOS (returns 10000 int) as you might
expect. Under windows 95 the interrupt doesn't appear to be hooked and
I get a divide by zero error.
Does anyone know a way of getting round this problem in 95 either with a
hack or a completely different (and better) solution to the problem.
Thanks in advance.
Graham Sturmy
PS. Sorry if its a tad long but this is about the shortest contained
program I could muster.
/* Code starts here (as if you didn't realise) */
#include <stdio.h>
#include <dpmi.h>
typedef long Fixed32;
__dpmi_paddr old_interrupt_vector;
#define inttofixed(_x) (((long)(_x)) << 16)
#define fixedtoint(_x) ((_x+32768) >> 16)
#define fixeddiv(x, y)                        \
({ Fixed32 __value, _arg1 = (x), _arg2 = (y); \
  asm ("xorl %%eax, %%eax;                  \n\
        shrdl $16, %%edx, %%eax;            \n\
        sarl $16, %%edx;                    \n\
        idivl %%ebx;"                         \
       :"=a" (__value)                        \
       :"d" (_arg1), "b" (_arg2)              \
       :"eax", "ebx", "edx");                 \
        __value;                              \
})
void divide_overflow(void) {
/* If the divide is void then we dont care what result is returned */
  asm ("popl %ebp;
        cmp $0, %ebx;
        jz 0f;
        shll $4, %ebx;
        iret;
       0:
        mov $0x00000001, %ebx;
        iret;");
}
/* This sets up the interrupt to catch numbers the fpu cant handle */
void set_divide_interrupt(void) {
  __dpmi_paddr new_vector;
  __dpmi_get_protected_mode_interrupt_vector(0x00, &old_interrupt_vector);
  new_vector.selector= _go32_my_cs();
  new_vector.offset32 = (long)divide_overflow;
  __dpmi_set_protected_mode_interrupt_vector(0x00, &new_vector);
}
/* This restores a previously setup interrupt */
void restore_divide_interrupt(void) {
    __dpmi_set_protected_mode_interrupt_vector(0x00, &old_interrupt_vector);
}
void main(void) {
  Fixed32 a,b;
  
  set_divide_interrupt();
  a = inttofixed(10000);
  b = 0;
  a = fixeddiv(a,b);
  printf("Fixed = %d, Int %d\n",a,fixedtoint(a));
  restore_divide_interrupt();
}
- Raw text -