delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1996/07/23/10:37:58

Date: Tue, 23 Jul 1996 15:32:20 +0100 (BST)
From: Graham Sturmy <sturmyg AT cs DOT man DOT ac DOT uk>
To: djgpp AT delorie DOT com
Subject: Win95 divide by zero errors
Message-Id: <Pine.SUN.3.91.960723152350.24821A-100000@n6k>
Mime-Version: 1.0

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 -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019