TURBO Pascal 3.0 projects



TURBO PASCAL Run Time Error

According to the principle that "no software is error free" also CP/M-80 TURBO Pascal 3.0 has some bugs which cannot be treated as features. Beneath some publications referring this subject I found a strange error myself.
The error happened when I tried to display free memory always as a positive integer. If there is much free memory the function memavail returns a negative integer. This may be performed by the following instructions:
            if memavail<0 then mfree:=65536.0+memavail
                          else mfree:=memavail;
The variable mfree must be of type real. The correction with the constant 65536.0 does take place in case of a negative integer in range $8000..$FFFF accordingly. The value $FFFF presents -1, therefore mfree holds 65535 being correct.
Now to the error: On a unique value of memavail only the machine is hanging up! This value is $8000. I took a look into the code and found the compiler routine for converting an integer to a real number at address $1008. This piece of code is responsible for the hang-up.
This function is as follows:
;
; Address $1008
;
int2real:
        ld      a,h             ; Test if integer=0
        or      l
        jp      z,int.0         ; If so, set result of real to zero
        bit     7,h             ; Test if integer<0
        ex      af,af'          ; Remember sign
        call    absNEG          ; Make integer absolute (positive only)
        ld      a,90h           ; Init exponent to start with
i2r.loop:
        add     hl,hl           ; Shift left integer
        dec     a
        bit     7,h             ; Until MSB is set
        jr      z,i2r.loop
        ld      b,h             ; Load resultat
        ld      c,l
        ld      de,0
        ld      h,d
        ld      l,a
        ex      af,af'          ; Get original sign
        ret     nZ              ; Was negative
        res     7,b             ; Make real positive
        ret
The routine I called "int.0" will ne found at address $07b2 of the compiler:
;
; Address $0b72
;
int.0:
        xor     a
        ld      l,a             ; Init real to zero
        ld      b,a
        ld      c,a
        ld      d,a
        ld      e,a
        ld      h,a
        ret
This routine looks problem-free. But what about the routine I called "absNEG" ?
;
; Address $0780
;
absNEG:
        bit     7,h             ; Test sign
        ret     z               ; End if $0000..$7FFF
        ld      a,h             ; Negate number
        cpl                     ; Returns $8000..$FFFF -> $8000..$0001
        ld      h,a
        ld      a,l
        cpl
        ld      l,a
        inc     hl
        ret
It is eye-catching that just the number hanging up the machine is identical as well as negative and positive number. And exactly that is the trouble. The routine "int2real" shifts register pair HL left and checks if bit 7 of register H is set or not. If not, the left shift proceeds.
But sfifting $8000 left results into a value of $0000 ! This leads to an endless loop waiting for bit 7 to be set - no more bits are available !
That explains the machine hang-up.

The only way to correct that is a patch which first checks the bit and then performs the shift. Unfortunately there is no room in the converter routine doing that - we need another place in memory. The fixed routine could look like this one:
;
; Address $1008
;
int2real:
        ld      a,h
        or      l
        jp      z,int.0
        bit     7,h
        ex      af,af'
;
; #### PATCH ####
;
        call    i2r.patch
i2r.loop:
        bit     7,h             ; Test bit
        jr      nz,i2r.ex       ; End if set
        add     hl,hl           ; Else shift
        dec     a
        jr      i2r.loop
i2r.ex:
;
; #### PATCH ENDE ####
;
        ld      b,h
        ld      c,l
        ld      de,0
        ld      h,d
        ld      l,a
        ex      af,af'
        ret     nz
        res     7,b
        ret
The patch requires one byte more than available !! Therefore I moved it to address $0106 of the compiler (here only the copyright message will be found):
;
; Address $0106
;
i2r.patch:
        call    absNEG
        ld      a,90h
        ret
For everybody who wants to install this patch type the following sequences using SID:
x>SID TURBO.COM                 # Call SID, loading TURBO.COM
CP/M 3 SID - Version 3.0
NEXT MSZE  PC  END
7980 7980 0100 D1FF
#S106                           # Indicate bytes to be modified
0106 6F CD                      # Modify values
0107 70 80
0108 79 07
0109 72 3E
010A 69 90
010B 67 C9
0108 68 .                       # Ready
#S1011                          # Part two
1011 80 06
1012 07 01
1013 3E CB
1014 90 7C
1015 29 20
1016 3D 04
1017 CB 29
1018 7C 3D
1019 28 18
101A FA F8
101B 44 .                       # End
#WTURBOP.COM                    # Write new file TURBOP.COM
00F1h record(s) written.
#^C                             # End
x>

Use this batch file (for SUBMIT) which performs the modification without keyboard typing.


Published in Klubzeitung No. 55 - März 1999.    Author: Werner Cirsovius