Date: Tue, 23 Jul 1996 15:32:20 +0100 (BST) From: Graham Sturmy To: djgpp AT delorie DOT com Subject: Win95 divide by zero errors Message-Id: Mime-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII 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 #include 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(); }