Date : Tue, 22 Jan 1985 12:54:00 MST (Tue)
From : Keith Petersen <W8SDZ@SIMTEL20.ARPA>
Subject: Major bug in Turbo Pascal version 2.00
TURBOBUG.TXT follows:
***** BUG REPORT *****
***** MAJOR BUG IN TURBO PASCAL V2.00 *****
July 1,1984
(updated December 1984)
The runtime routines do not handle a floating-point
(real) subtraction correctly. For some subtractions, the
correct difference is returned; for others, a zero is
returned. The following program demonstrates the bug:
program test;
begin
writeln(9.+(-6.0)); { Wrong value returned }
writeln(-1.0+(-1.0)); { Correct value returned }
writeln(1-2); { Correct value returned }
writeln(1.-2:10:2); { Wrong value returned }
writeln(1.-2.0); { Wrong value returned }
writeln(1-2.0); { Wrong value returned }
writeln(456 - 123.0); { Correct value returned }
end.
A value of zero is returned on those lines marked as 'wrong'.
The other lines return the correct difference.
VERSIONS TESTED AND FOUND OK (December 1984)
The following versions of Turbo have been checked for this bug
and are alright. Any versions for same OS, with higher serial
numbers, should be alright--but use the above test program to
be sure. The bug may be unique to MS-DOS versions.
Turbo ver 1.01A for CP/M-86 serial # 1225
Turbo ver 2.00B for CP/M-86 serial # 49036
Turbo ver 2.00B for MS-DOS serial #131821
THE CAUSE
After disassembling and tracing through a sample compiled
program, the error was located in the following code:
XXXX:12FA E84FFF CALL 124C ; Subtract
XXXX:12FD 7306 JNB 1305
XXXX:12FF 80F780 XOR BH,80 ; Handle negative
XXXX:1302 E863FF CALL 1268 ; numbers
XXXX:1305 8B4504 MOV AX,[DI+04] ; Is mantissa zero?
XXXX:1308 0B4502 OR AX,[DI+02]
XXXX:130B 0A4501 OR AL,[DI+01] ; ***** ERROR *****
XXXX:130E 740D JZ 131D ; Yes
XXXX:1310 F6450580 TEST BYTE PTR [DI+05],80 ; Normalize
XXXX:1314 750C JNZ 1322
(Comments have been added for clarity). This disassembled
code is located in the routines that handle addition and
subtraction (only the subtraction part is shown). The error
occurs when the routine tests to see if the result of the
subtraction is zero. It tests for a zero by "OR-ing" together
the five bytes of the mantissa (the instructions that do this
are at offsets 1305H to 130BH). If the mantissa is zero, then
the result of this "multiple-or" will set the zero flag. The
first of these instructions is a move of the word at [DI+4]
to AX. The next instruction takes the logical OR of AX and
[DI+2]. No problem so far. However, the last instruction is
"OR AL,[DI+1]", an instruction that operates on a byte and
not on a word. If the OR of the words at [DI+4] and [DI+2]
results in a word whose UPPER byte is NONZERO but whose LOWER
byte is ZERO, then the next instruction, the "byte-wise" OR,
will SET the zero flag if the byte at [DI+1] is zero. Notice
that the instruction at 130BH totally ignores the contents of
the upper byte of AX; the flags are set according to the
lower byte of AX only. This is what causes the error.
THE FIX
The fix to this bug is simple: simply exchange the order
of the two "OR" instructions. This way, the zero flag is set
according to a full 16-bit OR and not an 8-bit one.
IMPORTANT: Only persons familiar with the operation of DEBUG
should attempt the following. Using DEBUG, the following
sequence of commands can be used to fix the bug:
Assumptions and notes in the following:
1) ONLY WORK ON A COPY OF TURBO! DO NOT USE
YOUR MASTER COPY!
2) The sequence of commands shown below writes
out the fixed version to the file
'turbo.com'
3) Make sure that you have version 2.00
4) 'turbo.com' must be in the current
directory on drive B.
5) DOS 2.00 or above is being used (the
debugger in DOS 1.00 and 1.10 does not have
the 'assemble' command).
6) Be sure to verify that the code in the
compiler is the same as that shown below
initially. After the changes are made, be
sure to verify that the changes have been
made correctly before writing the fixed
version out to disk.
B>debug turbo.com
-u 12fa <- Verify the following locations
XXXX:12FA E84FFF CALL 124C
XXXX:12FD 7306 JNB 1305
XXXX:12FF 80F780 XOR BH,80
XXXX:1302 E863FF CALL 1268
XXXX:1305 8B4504 MOV AX,[DI+04]
XXXX:1308 0B4502 OR AX,[DI+02]
XXXX:130B 0A4501 OR AL,[DI+01]
XXXX:130E 740D JZ 131D
XXXX:1310 F6450580 TEST BYTE PTR [DI+05],80
XXXX:1314 750C JNZ 1322
XXXX:1316 E8F9FE CALL 1212
XXXX:1319 FE0D DEC BYTE PTR [DI]
-a 1308 <- Make changes
XXXX:1308 or al,[di+1]
XXXX:130E or ax,[di+2]
XXXX:1311 <- Press 'enter'
-u 12fa <- Verify that the changes are correct
XXXX:12FA E84FFF CALL 124C
XXXX:12FD 7306 JNB 1305
XXXX:12FF 80F780 XOR BH,80
XXXX:1302 E863FF CALL 1268
XXXX:1305 8B4504 MOV AX,[DI+04]
XXXX:1308 0A4501 OR AL,[DI+01]
XXXX:130B 0B4502 OR AX,[DI+02]
XXXX:130E 740D JZ 131D
XXXX:1310 F6450580 TEST BYTE PTR [DI+05],80
XXXX:1314 750C JNZ 1322
XXXX:1316 E8F9FE CALL 1212
XXXX:1319 FE0D DEC BYTE PTR [DI]
-w <- Save fixed version of turbo
Writing 8E80 bytes
-q
B>
<end of fix>
OTHER NOTES ABOUT TURBO
One cannot set breakpoints in TURBO using DEBUG. It
seems that TURBO uses the breakpoint interrupt for some
hideous reason. If one attempts to set breakpoints, the
system will probably crash. Tracing, however, does seem to
work. The above bug was tracked down only after hours of
tracing (by machine and by hand) and disassembling.
--------
- - - - - - - End forwarded message