home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c329 / 2.img / EXAMPLES / DIVZ.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-11-07  |  4.9 KB  |  171 lines

  1. /*
  2.  * divz.c
  3.  *
  4.  * Purpose: demonstrates principles used in creating a
  5.  * user-written numeric exception handler.
  6.  * To compile for an 80287:
  7.  *      cc divz.c -DNDP287=1 -n0
  8.  * To compile for an 80387:
  9.  *      cc divz.c -DNDP387=1 -n2
  10.  * To compile for an mW1167:
  11.  *      cc divz.c -DNDP1167=1 -n4
  12.  */
  13.  
  14. #include <stdio.h>
  15. #include <dos.h>
  16.  
  17. #define NONE    0
  18. #define mW1167  1
  19. #define i80387  2
  20. #define i80287  3
  21. #define EVAL    0xffffffff      /* error value returned */
  22.                                 /* by enab_ex_() */
  23. #define TRUE    1
  24. #define FALSE   0
  25.  
  26. extern void     exit();
  27. extern void     bcopy();
  28. extern double   temp_dbl();
  29.  
  30. void    n_ex_hdl();             /* New exception handler. */
  31. int     display_ndp();          /* display NDP state after*/
  32.                                 /* calling stndpenv_() */
  33.  
  34. double  d1, d2 = 1.0, d3 = 0.0;
  35.  
  36. #if NDP287==1
  37. struct excep287 buff;           /* used for 80287. See DOS.H */
  38. #endif
  39.  
  40. #if NDP387==1
  41. struct excep buff;              /* used for 80387. See DOS.H */
  42. #endif
  43.  
  44. #if NDP1167==1
  45. struct wexcep buff;             /* used for mW1167. See DOS.H */
  46. #endif
  47.  
  48. unsigned        type;
  49. main()
  50.  
  51. {
  52.         unsigned        save_cw, emask;
  53.         int             okay;
  54.  
  55.         type = ndptype_();      /* get type of NDP */
  56.         if (type == NONE) {
  57.                 printf ("No NDP present. Exiting\n\n");
  58.                 putchar('\7');  /* beep */
  59.                 exit(1);
  60.         }
  61.  
  62.         init_ndp_();    /* Initialize the NDP .Masks all */
  63.                         /* errors except invalid operations */
  64.  
  65.         type = stndpenv_(&buff);  /* Dump NDP numeric and */
  66.                            /* environment registers into buffer */
  67.  
  68.         okay = display_ndp();   /* display contents of NDP */
  69.         if (!okay) {
  70.                 exit(1);
  71.         }
  72.                                 /*Set up new exception handler*/
  73.         if (!set_ex_hdl_(n_ex_hdl)) {
  74.                 printf("\nCan't set up new exception handler.\n");
  75.                 putchar('\7');  /* beep */
  76.                 exit(1);
  77.         }
  78.  
  79.         emask = ZM;
  80.         save_cw = enab_ex_(&emask); /* enable zero divide */
  81.                                     /* exception trap */
  82.         if (save_cw == EVAL) {
  83.                 printf("\nProblem in enab_ex()\n");
  84.                 putchar('\7');  /* beep */
  85.                 exit(1);
  86.         }
  87.  
  88.         d1 = d2/d3;             /* Force division by zero */
  89.  
  90.         printf ("The quotient is %20.14e\n",d1);
  91.  
  92. }       /* end of main */
  93.  
  94. #include "\\c200src\\dispndp.c"
  95.  
  96. /* New exception handler. */
  97.  
  98. void    n_ex_hdl()
  99.  
  100. /* Control branches to this routine (after it is installed)
  101.  * anytime an NDP exception occurs and that exception has
  102.  * been unmasked in the control word.
  103.  */
  104.  
  105. {
  106.         int             i;
  107.         unsigned        type;
  108.  
  109. static  char large_value [] = {
  110.                 0xff,
  111.                 0xff,
  112.                 0xff,
  113.                 0xff,
  114.                 0xff,
  115.                 0xff,
  116.                 0xff,
  117.                 0xff,
  118.                 0xfb,
  119.                 0x43
  120.         };
  121.  
  122.  
  123.         printf("\nAn NDP exception has just occurred.\n\n");
  124.  
  125. /* On entry the one or more error bits in the NDP status
  126.  * word are on. The error handler calls stndpenv_() to
  127.  * dump NDP numeric and environment registers into the
  128.  * buffer. A side effect of this is that the chip is
  129.  * reinitialized, with all exceptions masked and all
  130.  * error bits cleared.
  131.  */
  132.         type = stndpenv_(&buff);
  133.  
  134.         display_ndp();  /* Display NDP state. */
  135.  
  136. /* The default (masked) response of the 80387 to a division
  137.  * by zero is to return an infinity whose sign is the
  138.  * exclusive OR of the signs of the two operands. The
  139.  * programmer has decided that it would be better if the
  140.  * program would return a very large positive number. The
  141.  * code below tests the zero divide bit in the status word.
  142.  * If this is indeed the current error, the program moves a
  143.  * very large value into the memory area for ST0 (the lowest
  144.  * 80387 numeric register) and then calls ldndpenv_()
  145.  * which reloads the buffer into the 80387 and clears the
  146.  * error bits in the status word, otherwise another
  147.  * interrupt would happen immediately.
  148.  * Note that ldndpenv_() will NOT work with an 80287,
  149.  * because of a bug in the interface between a protected
  150.  * mode 80386 and an 80287.
  151.  *
  152.  */
  153.  
  154. #if NDP387==1 || NDP287==1
  155.         if (buff.sw & ZM) {
  156.                 bcopy (&large_value[0], &buff.st0[0], 10);
  157.         }
  158.  
  159.         ldndpenv_(&buff);       /* load buffer back into NDP. */
  160.                                 /* This function clears the */
  161.                                 /* error bits in the status word */
  162.                                 /* lest an NDP exception */
  163.                                 /* immediately recur */
  164. #endif
  165.  
  166. /* Control now returns to the main program, right after
  167.  * the instruction which caused the division by zero.
  168.  */
  169.  
  170. }
  171.