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 -