I found the solution. It is this (Please pass this info to the
programmer so that he would know how to fix it):
From (e-mail address removed) Wed Oct 27 05:24:00 2004
Subject: Crt.delay problem on a fast PC
Date: Wed, 27 Oct 2004 05:24:00
From: (e-mail address removed) (Timo Salmi)
124. *****
Q: Curing Crt initialization runtime error 200 on fast machines
A: I was not familiar with this problem myself since I have run
only sub-200MHz PCs, but I'll store here what I learned from the
excellent discussion on the subject in by programmers much more knowledgeable than I. First of all the Crt
initialization crash only concerns TP and BP bersions 7.00 and 7.01.
Quoting Osmo Ronkanen: "The earlier versions had a bug that caused
only delays to be too slow from machines 386-33 or so on. This was
fixed in version 7.0 and the fix caused a new bug i.e. the division
by zero error on machines that were 55 times faster than the ones on
which the old bug appeared."
First some references. Please be aware that I can't guarantee
that the URL addresses below will stay current.
Prevent the "Divide by 0" error, Roger Donais. You'll need
ftp://users.southeast.net/private/rdonais/rdelay.zip
ftp://users.southeast.net/private/rdonais/util.zip
NewDelay, Fix for bug in Crt unit's Delay procedure, by F.Heckenbach
http://fjf.gnu.de/programs.html#NewDelay
Problems with the Crt.Delay procedure, by Dr John Stockton
http://www.merlyn.demon.co.uk/pas-r200.htm
Fix for "Runtime Error 200" bug of Borland Pascal 7 on fast PCs,
by Klaus Hartnegg
http://www.brain.uni-freiburg.de/~klaus/pascal/runerr200/
ERROR 200
iv. by zero
A posting in
http://www.deja.com/getdoc.xp?AN=721178015
Roger's solution is also available as (or whichever version numbers
are current when you read this):
4903 Jan 20 1997 ftp://garbo.uwasa.fi/pc/turbopas/rdelay10.zip
rdelay10.zip Prevent the divide-by-0 Crt error on fast machines,
R.Donais
:
56849 Jun 21 1997 ftp://garbo.uwasa.fi/pc/turbopas/rutil10.zip
rutil10.zip Turbo Pascal utilities by R.Donais, (needed by rdelay)
Then there also is
ftp://garbo.uwasa.fi/pc/turbspec/bp7patch.zip
CRT Delay patch for TURBO.TPL 48,432 10-27-92 7:00a
and probably later versions in circulation. Furthermore, there is a
replacement
30394 Aug 14 1999 ftp://garbo.uwasa.fi/pc/turbopas/crt.zip
crt.zip Replacement CRT units for Turbo/Borland Pascal, P.Scragg
The bug is in the Crt routine's initialization code. For example
Osmo Ronkanen writes "In the initialization code TP runs the delay
loop for one clock cycle. Then the result is divided by 55
(milliseconds in the cycle) to get loop size for one millisecond
delay. Now if that becomes greater than 65535 then the divide
overflow interrupt is called and that causes the runtime error to be
signaled." Dr John Stockton wrote "... initialize contains the
dreaded MOV 55 ; DIV CX"
A trivial solution to the problem is not to use the Crt unit at
all and to use the 'Wait' procedure from the item "If Delay
procedure does not work properly, how do I fix it?" instead of the
Crt.Delay.
Frank Heckenbach wrote about the 'Wait' procedure. "Besides the
fact that it doesn't prevent the runtime error 200 [if uses Crt is
included], as Osmo explained, this version's accuracy is only 1/18.2
seconds in contrast to 1 ms of the original Delay which should be
stuck to in replacements, IMHO."
Frank continued: "I'd also like to draw your attention to another
problem that the above version as well as the original Delay code
suffer from, namely busy waiting, this means executing some code
during the most time of the delay. Whereas this doesn't matter on a
single tasking DOS, it will significantly reduce the CPU time
available to other processes when run under multi tasking OS's. (And
such environments should really be taken into account these days.)"
Osmo Ronkanen posted the following solution for TP 7.0 which is
brief enough to be included in here. Osmo wrote about its previous
version: "[This runtime fix] does not disable delay. Delay works
just as it does before on machines that are slower than those that
cause problem. On faster machines it also works but as the counter
is set to 65535 instead of its true value of that would be something
higher the delays get slower and slower. So on machines that are
twice as fast as the ones that just cause the error the delays are
half as log as they should be." (Timo's addition. If the resolution
of 'Wait' procedure is sufficient for the programmer's purposes,
then it is better to use FDelay+Wait than FDelay+Delay.)
Unit Fdelay; { Place this before CRT. Real mode only }
interface
const dfix:word=1; { call delay() dfix times }
implementation
uses dos;
procedure oldints; assembler; { "variables" in the code segment }
asm dd 0,0 end;
Procedure error;
begin
runerror(200);
End;
Procedure Int0; assembler;
asm
cmp cx,55 { If CX<>55 we are at some other point }
je @ok
sti
call error
@ok:
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;
{ Int21h handler removes the int0 handler (as well as itself) from
the memory when CtrlBreak vector is set by CRT right after
calculating the delay counter. Note DS does NOT point to the data
segment when this is called }
Procedure Int21h; assembler;
asm
cmp ax,$251B
jne @old { Not setint 1Bh? }
push es; push si; push di
mov si,offset oldints
xor di,di
mov es,di
cld
segcs; movsw
segcs; movsw { restore int 0 }
mov di,$21*4
segcs; movsw { restore int 21h }
segcs; movsw
pop di; pop si; pop es
@old: db $2e,$ff,$2e { jmp far indirect cs:[oldints+4] }
dw offset oldints+4
end;
type tr=record int0,int21
ointer; End;
pr=^tr;
begin
GetIntVec(0,pr(@oldints)^.int0);
GetIntVec($21,pr(@oldints)^.int21);
SetIntVec(0,@int0);
SetIntVec($21,@int21h);
end.
Roger Donais emailed me the following version based on Osmo's codes.
It is for TP 4.0-7.0. Just put
uses FDelay, Crt;
at the top of your program. Nothing else is needed. Not even a call
at the beginning of the main program. This is a nice end result of
the concerted efforts of the newsgroup.
Please note, however, that the code below does not have all the
safeguards that the code above does according to its author.
UNIT FDelay;
{ Purpose is to intercept 1st divide by zero error and if it appears
it could be from CRT to allow it to pass thereby allowing TP 7.0
(real mode) to use CRT (w/o delay) on systems with fast processors.
This solution will not work w/ multiple divide by 0 errors and may
leave the system unstable if an error occurs during TP exit process.
}
INTERFACE
USES DOS;
IMPLEMENTATION
VAR Old0 : Pointer;
TPExit: Pointer;
PROCEDURE Int0 (Flags, CS, IP, AX, BX, CX, DX, SI, DI, DS, ES, BP
: Word); interrupt;
BEGIN
SetIntVec(0, Old0);
If CX = 55 Then Begin
AX := 65535;
DX := 54;
End; { Else error recurs w/ original int0 handler }
END;
PROCEDURE OnExit; FAR;
BEGIN
ExitProc := TPExit;
SetIntVec(0, Old0);
END;
BEGIN
GetIntVec(0, Old0);
SetIntVec(0, @Int0);
TPExit := ExitProc;
ExitProc := @OnExit;
END.
If you wish to solve the problem by not using the Crt unit at all,
below is a list of all the Crt unit procedures and functions and the
replacements that yours truly (Timo) has released or that can be
found in the FAQ.
Crt Replacement Where
--- ----------- -----
AssignCrt .. ..
ClrEol .. ..
ClrScr ClrScreen,CLS,CLS40 FAQ #117
Delay Wait FAQ #67
DelLine .. ..
GotoXY GOATXY TSUNTG in tspa*.zip
HighVideo .. ..
InsLine .. ..
KeyPressed KEYPREFN TSUNTM in tspa*.zip
LowVideo .. ..
NormVideo .. ..
NoSound .. ..
ReadKey READKEFN,RDENKEFN TSUNTM in tspa*.zip
Sound AUDIO TSUNTD in tspa*.zip
TextBackground ..
TextColor ..
TextMode TextSet /pc/turbopa7/textset.zip
WhereX WHEREXFN TSUNTG in tspa*.zip
WhereY WHEREYFN TSUNTG in tspa*.zip
Window ..
Q2: If the delay() statement isn't called, does the code compile
bad anyway?
A2: Had you first carefully read the first part of this FAQ item
#124 "Curing Crt initialization runtime error 200 on fast machines"
you would have noted "The bug is in the [TP7] Crt routine's
initialization code". It is NOT calling delay() that causes the
error. It is the "Uses Crt". Thus you can't avoid the problem by
just not using delay() if you insert the Crt unit into a TP 7.0
program on a fast PC. The error is a Crt initialization error, not a
delay() error. The (further) problem with delay() is that it can be
inaccurate. That aspect is covered in the item #67 "If Delay
procedure does not work properly, how do I fix it?".
A3: A terminology comment from Paul Schlyter: "BTW it's not really
a "divide by 0", but rather a division overflow, where the 32-bit
numerator divided by the 16-bit denominator makes the quotient
overflow 16 bits. However, the same hardware interrupt is generated
for division overflow as for division by zero."
A4: If you have an executable with this error but you do not have
the source code to recompile, see
3511 Feb 1 1999 ftp://garbo.uwasa.fi/pc/turbopa7/tfix.zip
tfix.zip Loader source to avoid TP 7.0 Crt RTE200, Osmo Ronkanen
or
20739 Sep 6 2000 ftp://garbo.uwasa.fi/pc/turbopa7/crtfix15.zip
crtfix15.zip Borland Pascal Crt unit RTE 200 fix, freeware, E.Toder
A5: Also see the (further) references in the mini-FAQ regularly
posted by Pedt Scragg to
ANONYMOUS wrote:
Is the prgram written n Borland/Turbo Pascal? If so then the error
relates to using a dos program (in particular crt Unit) on fast PCs.
I
think there is a patch for it. I will sarch for it and come back to
you.
Regards,
Mike wrote:
Hi, at workk our PCs are running XP Pro sp2. We need to run a circa
1998
psychological testing program on PCs running XP Pro sp2. When I
attempt to
runing the DOS program from the Run Line (Start\Run\CMD\) T
The
program won't run. but the following error message is generated:
runtime error 200 at 33d4:0091
I googled the error messagew but didn't get any links.
Any suggestions what I need to do to get this program working?