TURBO PASCAL Run Time ErrorNach 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 retDie 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 retDiese 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 retHier 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 retEs 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 retFü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 |