TURBO Pascal 3.0 Projekte



TURBO PASCAL Run Time Error

Nach dem Motto "Keine Software ist fehlerfrei" besitzt auch CP/M-80 TURBO Pascal 3.0 einige Bugs, die leider nicht als Features durchgehen können. Neben einigen Publikationen zu diesem Thema habe ich einen bisher nirgends beschriebenen Fehler gefunden, der schon recht kurios ist.
Aufgetreten ist dieser Fehler bei mir, als ich versuchte, den freien Speicher nicht als negative Zahl, wie von der Funktion memavail geliefert, wenn viel Speicher frei ist, sondern als positive Zahl zu erhalten. Der Trick ist die folgende Anweisung:
            if memavail<0 then mfree:=65536.0+memavail
                          else mfree:=memavail;
Hierbei ist die Variable mfree vom Typ real. Die Korrektur mit der Konstanten 65536.0 erfolgt bei negativer integer Zahl, also im Breich $8000..$FFFF. Hierbei ist $FFFF -1, also steht in mfree 65535, was ja richtig ist.
Nun zum Fehler: Bei einem einzigen Wert von memavail hängt sich der Rechner auf! Dieser Wert ist $8000. Ich habe mir mal den Code angeschaut und im Compiler bei Adresse $1008 die Funktion gefunden, die eine integer in eine real Zahl wandelt und für den Hänger verantwortlich ist.
Diese Funktion sieht wie folgt aus:
;
; Adresse $1008
;
int2real:
        ld      a,h             ; Test ob integer=0
        or      l
        jp      z,int.0         ; Wenn ja, real Resultat Null setzen
        bit     7,h             ; Test ob integer<0
        ex      af,af'          ; Vorzeichen merken
        call    absNEG          ; Integer absolut (nur positiv)
        ld      a,90h           ; Startexponent laden
i2r.loop:
        add     hl,hl           ; Integer solange links schieben
        dec     a
        bit     7,h             ; Bis das hoechste Bit gesetzt ist
        jr      z,i2r.loop
        ld      b,h             ; Resultat holen
        ld      c,l
        ld      de,0
        ld      h,d
        ld      l,a
        ex      af,af'          ; Altes Vorzeichen holen
        ret     nZ              ; War negativ
        res     7,b             ; Real positiv machen
        ret
Die Routine, die ich "int.0" genannt habe, findet sich in Adresse $07b2 des Compilers:
;
; Adresse $0b72
;
int.0:
        xor     a
        ld      l,a             ; Real Resultat auf Null setzen
        ld      b,a
        ld      c,a
        ld      d,a
        ld      e,a
        ld      h,a
        ret
Diese Routine sieht problemlos aus. Was ist nun mit der von mir genannten Routine "absNEG" ?
;
; Adresse $0780
;
absNEG:
        bit     7,h             ; Test Vorzeichen
        ret     z               ; Ende bei $0000..$7FFF
        ld      a,h             ; Negative Zahl bilden
        cpl                     ; als $8000..$FFFF -> $8000..$0001
        ld      h,a
        ld      a,l
        cpl
        ld      l,a
        inc     hl
        ret

Hier fällt auf, daß ausgerechnet die Zahl, bei der der Rechner hängt, sowohl negativ als auch positiv identisch ist. Und hier liegt das Problem. In der Routine "int2real" wird HL links geschoben und dann getestet, ob das Bit 7 vom Register H gesetzt ist. Falls nicht, wird weitergeschoben.
Schiebt man den Wert $8000 links, dann erhält man $0000 ! Jetzt kann man lange schieben, bis man das Bit 7 findet, es ist kein Bit mehr da !
Klar, daß der Rechner hängt.

Will man dieses Problem beseitigen, so bleibt nur ein Patch, der erst das Bit prüft und dann schiebt. Leider reicht der vorhandene Platz der Routine nicht aus, so daß ein freien Platz gesucht werden muß. Die gepatchte Routine könnte wie folgt aussehen:

;
; Adresse $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             ; Bit testen
        jr      nz,i2r.ex       ; Ende wenn gesetzt
        add     hl,hl           ; Nun schieben
        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
Es fehlt genau ein Byte !! den Patch habe ich bei mir in Aresse $0106 des Compilers gepackt, dort steht nur ein Copyright Hinweis:
;
; Adresse $0106
;
i2r.patch:
        call    absNEG
        ld      a,90h
        ret
Für alle, die diesen Patch einfahren wollen, hier die Anweisungen für SID:
x>SID TURBO.COM                 # SID aufrufen, TURBO.COM laden
CP/M 3 SID - Version 3.0
NEXT MSZE  PC  END
7980 7980 0100 D1FF
#S106                           # Angabe für Änderung
0106 6F CD                      # Werte ändern
0107 70 80
0108 79 07
0109 72 3E
010A 69 90
010B 67 C9
0108 68 .                       # Änderung fertig
#S1011                          # Zweiter Teil
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 .                       # Ende
#WTURBOP.COM                    # Neue Datei TURBOP.COM schreiben
00F1h record(s) written.
#^C                             # Ende
x>

Um das Tipseln im SID überflüssig zu machen, hier eine SUBMIT Datei, die das automatisch macht.


Abgedruckt in Klubzeitung Nr. 55 - März 1999.    Autor: Werner Cirsovius