    Subject: Re: Runtime error 200
       Date: 28 Oct 1999 17:19:35 +0300
      From: ronkanen@cc.helsinki.fi (Osmo Ronkanen)
 Organization: University of Helsinki
 Newsgroups: comp.lang.pascal.borland

In article <38180CB7.142CABCE@po.jaring.my>, EDP  <ggcm@po.jaring.my> wrote:
>
>runtime error 200 at 037F:0091 on Pentium II and Celeron PC.
>
>any solution or patches?
>

Use RT200FIX as the first unit of the program. Use RT200DEL after
CRT.PAS in every module (main program/unit) that uses Delay(). There
is no need to use RT200SUB directly.

The fix is for TP 7.0 and real mode only. In pre-7.0 or PM there is
no fix, nor interference.

The execution first gets to the Initialization code of RT200Sub. It
hooks the int 0 handler. Then the execution goes to the CRT
initialization code. If it RTE200's then the int 0 handler in RT200Sub
is activated and DX:AX is divided by two and Dfix multiplied by 2. The
execution then returns to the division instruction. It can fail again
causing further division (and multiplication) by two until it does not
fail. After the CRT initialization the initialization code of RT200Fix
itself is executed. It just unhooks the int 0 handler of RT200Sub so that
further divisions by zero will directly trigger the TP int 0 handler
(That is established in the system unit initialization which always is
executed at the very beginning)

As the Dfix is multiplied by two every time the DX:AX is divided by
two in the loop handler then the proper delays can be restored by
multiplying the ms count given to delay by Dfix. However, to avoid
overflows a loop is better choice. RT200Del does just that in its
Delay. The overhead caused by the loop is insignificant.
 
 

-----------------------RT200FIX.PAS------------------------------

Unit RT200fix;

interface

uses RT200Sub,crt,dos;

implementation

{$ifdef ver70}
{$ifdef msdos}
Begin
  SetIntVec(0,Int0Save);   { Restore the Int 0 handler }
{$endif}
{$endif}
End.

-----------------------RT200DEL.PAS------------------------------

Unit RT200Del;

interface

uses RT200Fix,CRT,RT200Sub;

Procedure Delay(ms:word);

implementation

Procedure Delay(ms:word);
var i:word;
Begin
  for i:=1 to Dfix do CRT.Delay(ms);
End;

end.

-----------------------RT200SUB.PAS------------------------------

Unit RT200Sub;

interface

const dfix:word=1;       { call delay() dfix times }

Var int0Save:pointer;

implementation

{$ifdef msdos}
{$ifdef ver70}

uses dos;

Procedure Int0; assembler;
          asm
          shr dx,1        { divide dx:ax by 2 }
          rcr ax,1
          shl Dfix,1      { multiply Dfix by 2 }
          iret            { return to the DIV (286+) }
          end;
 

begin
  GetIntVec(0,Int0Save);
  SetIntVec(0,@int0);
{$endif}
{$endif}
end.
Osmo
