Catching maths errors (eg divide by zero) 
Author Message
 Catching maths errors (eg divide by zero)

Is there an easy way to catch errors in mathematical calculations (such
as divide by zero, or range errors) which doesn't involve checking all
the parameters in an equation before calculating it, but which doesn't
just dump me back to DOS? I tried adding a procedure into the ExitProc
chain which, when a certain error was found, jumped back into the code
using a LongJump type construct, but that didn't work (the LongJump was
okay, but the program crashed on a proper exit). Is there something wrong
with this method, or have I just got a bug in my implementation of it?

Mark.
--

function MeaningOfLife :integer; begin MeaningOfLife := 6 * 9 end;



Wed, 18 Jun 1902 08:00:00 GMT  
 Catching maths errors (eg divide by zero)
Install your own error handler to handle run-time errors. Sample code is
in the BP7 manual.
Bri


Wed, 18 Jun 1902 08:00:00 GMT  
 Catching maths errors (eg divide by zero)
Hi Mark!

MR> Is there an easy way to catch errors in mathematical calculations
This code should do it:

===cut here===
unit exceptions;
(*$s-*)

(*
Exceptions in TP! (c) 1993 by Jasper Neumann / SCP GmbH Aachen.
DOS, DPMI, OS/2, probably Win; *not* in overlays.

The following scheme should be applied:

  case exception of
    0: begin
      (your code)
      end_exception;
      end;
    err_1: err_1_handler;
    ...
    err_n: err_n_handler;
    else raise_current;
    end;

The case 0 always contains the code you want to protect.
The line "else raise_current;" submits not handled exceptions to the next
exception handler.

Explicit raising is done with  raise(x)  (x<>0).

Program layout:

  program xxx;
  ...
  begin
    (init code without exceptions)
    install_std_err;
    ...
*)

INTERFACE

const e_invalid_raise=250;
(* Exception raised without an exception handler installed *)

type
  tp_exception=^t_exception;
  t_exception=record
    link: tp_exception;
    _bp,_ip,_cs: word;
    end;
(* Non-public exception structure. *)

const cur_ex: tp_exception=nil;
(* Non-public pointer to current exception block. *)

const err_no: word=0;
(* Argument of last raise. *)

procedure halt(x:word);
(* System override to really quit the program. *)

function exception:word;
(* Creates an exception handler. *)
inline(
   $0e                  (*   push   cs                          *)
  /$e8/$00/$00          (*   call   here                        *)
                        (* here:                                *)
  /$58                  (*   pop    ax -- ip                    *)
  /$05/$18/$00          (*   add    ax,start-here               *)
  /$50                  (*   push   ax -- ip                    *)
  /$55                  (*   push   bp                          *)
  /$ff/$36/>cur_ex+2    (*   push   [cur_ex+2]                  *)
  /$ff/$36/>cur_ex      (*   push   [cur_ex]                    *)
  /$8c/$16/>cur_ex+2    (*   mov    [cur_ex+2],ss               *)
  /$89/$26/>cur_ex      (*   mov    [cur_ex],sp                 *)
  /$31/$c0              (*   xor    ax,ax -- no exception       *)
  );                    (* start:                               *)

procedure end_exception;
(* Leaves the current exception handler.*)
inline(
   $8f/$06/>cur_ex      (*   pop    [cur_ex]                    *)
  /$8f/$06/>cur_ex+2    (*   pop    [cur_ex+2]                  *)
  /$83/$c4/$06          (*   add    sp,6                        *)
  );

procedure raise(x:word);

procedure raise_current;

procedure install_std_err;
(* Introduction of an standard error handler to catch runtime errors. *)

IMPLEMENTATION

const exitsave: pointer=nil;

procedure halt(x:word);
begin
  cur_ex:=nil;
  system.halt(x);
  end;

procedure raise(x:word);
begin
  err_no:=x;
  if (x=0) or (cur_ex=nil) then  runerror(e_invalid_raise);
  asm
    mov    ss,word ptr [cur_ex+2]
    mov    sp,word ptr [cur_ex]
    pop    word ptr [cur_ex]
    pop    word ptr [cur_ex+2]
    mov    ax,[x]
    pop    bp
    retf
    end;
  end;

procedure raise_current;
begin
  raise(err_no);
  end;

procedure std_err;  FAR;
begin
  if (cur_ex<>nil) and (exitcode<>0) then begin

    raise(exitcode);
    end;
  exitproc:=exitsave;
  end;

procedure install_std_err;
begin
{   if exitsave<>nil then  ... }
  exitsave:=exitproc;

  end;

end.
===cut here===

Greetinx Jane



Wed, 18 Jun 1902 08:00:00 GMT  
 Catching maths errors (eg divide by zero)
I can help you with the division by zero problem.  When a division by
zero occurs interrupt 0 is executed.  You can replace interrupt 0 with
one of your own, that will not hang your PC.  The code for this is as
follow :

program DivideByZero;

uses dos;

var
  Zero     : byte;
  Int0Save : pointer;

procedure ZeroDivide (Flags, CS, IP, AX, BX, CX, DX, SI, DI, DS, ES,
                             BP : word);
interrupt;

begin

  writeln('Divide by 0!!!);

end;

begin

  getintvec($00, Int0Save);

  Zero := 0;

  writeln(20 div 2);
  writeln(10 div 0);
  writeln(60 div 2);

  setintvec($00, Int0Save);

end.

I only typed this code in the editor, I did not compile it, if you have a
problem with the code e-mail me please.

CCC



Wed, 18 Jun 1902 08:00:00 GMT  
 Catching maths errors (eg divide by zero)
The line writeln(10 div 0) should have been writeln(10 div Zero).  The
same effect but just more fancy.

CCC



Wed, 18 Jun 1902 08:00:00 GMT  
 Catching maths errors (eg divide by zero)


Quote:
> I can help you with the division by zero problem.
> (...)

Thanks for the tip. Unfortunately, divide by zeros are only one of the
errors which I need to catch :(

I have no achieved the result, though, using the LongJump method I was
originally playing with. The cause of my problems turns out to have been
rather simple; the procedure I had chained into the ExitProc chain I had
forgotten to declare as a far procedure. Oops!

Mark.
--

function MeaningOfLife :integer; begin MeaningOfLife := 6 * 9 end;



Wed, 18 Jun 1902 08:00:00 GMT  
 Catching maths errors (eg divide by zero)


Quote:

> MR> Is there an easy way to catch errors in mathematical calculations
> This code should do it:

Thanks. Actually, that's pretty much how I was trying to do it (a few
cosmetic differences, and a few nice touches that I liked), except for
one small part:

Quote:
> procedure std_err;  FAR;

                      ^^^

I can't believe that I missed that - I deal with ExitProc all the time.
Which makes me feel rather silly!

Mark.
--

function MeaningOfLife :integer; begin MeaningOfLife := 6 * 9 end;



Wed, 18 Jun 1902 08:00:00 GMT  
 Catching maths errors (eg divide by zero)


Quote:
> Install your own error handler to handle run-time errors. Sample code is
> in the BP7 manual.

I had this bit done okay (or so I thought - see my other post). The
problem appeared to be in jumping back into the code and continuing as if
nothing had happened. Once I had the run-time error handler installed
correctly, though, it all worked fine.

Mark.
--

function MeaningOfLife :integer; begin MeaningOfLife := 6 * 9 end;



Wed, 18 Jun 1902 08:00:00 GMT  
 
 [ 8 post ] 

 Relevant Pages 

1. divide by zero error/mathmatic overflow error?

2. uses crt; divide by zero error

3. Divide by Zero CRT Error

4. Divide by Zero error

5. Pascal_7.0_in_Pentium_II : Divide by zero error

6. divide by zero error when using CRT;

7. TP ver7, error 200 (divide by zero), with real mode programs

8. D3 - Divide By Zero Error on Post...

9. btrieve divide by zero error

10. BDE error : Divide By Zero

11. GPF's and divide by zero errors..

12. BP7, E200, Divide By Zero

 

 
Powered by phpBB® Forum Software