★ APPLICATIONS ★ PROGRAMMATION ★ BASIC-Zeilen perfekt verstecken ★ |
Supersave (CPC Amstrad International) | Applications Programmation |
Wenn man sich näher mit der Art und Weise auseinandersetzt, mit der der BASIC-Interpreter des LOCOMOTIVE BASIC (auf Maschinensprachenebene) eingegebene BASIC-Zeilen abarbeitet, kommt man zu einigen ganz verblüffenden Resultaten! Kurz einige grundlegenden Dinge zur Ablage von BASIC-Zeilen im Speicher des CPC's: (alle ab jetzt angegebenen Zahlenwerte sind Hexadezimalzahlen!)
Wozu ist nun dieser Offset zu Begin einer BASIC-Zeile eigentlich gut? Vereinfacht ausgedrückt dient er dem Interpreter nur dazu, eine Keile möglichst schnell im Speicher wiederzufinden. Die Arbeitsweise des Interpreters soll ein kleines Beispiel verdeutlichen: Sie haben ein BASIC-Programm geschrieben, das in Zehnersehritten durchnummeriert ist und im Zeilenbereich 10 - 1000 liegt. Durch die Direkteingabe des Befehls: LIST 500- wollen Sie nun den Bereich ab Zeilennummer 500 listen lassen. Der Interpreter fängt nun am BASIC-Speicheranfang an, die ge-v* ünschte Zeilennummer zu suchen. Nun wäre es ein sehr zeitraubendes Unternehmen, alle BASIC-Zeilen, die kleiner als 500 sind, komplett »abzuklappern«. Der Interpreter »merkt« sich daher die aktuelle Zeilenlänge (also den Offset), vergleicht die aktuelle Zeilennummer mit der gewünschten und braucht, falls keine Übereinstimmung besteht, nur den Offset zum aktuellen Programmzähler zu addieren, um somit sehr schnell zur nächsten Zeilennummer zu springen. Datazeilen, die von einem RESTORE-Befehl angesprochen werden, werden auf die gleiche Art »gefunden«, Bei GOTO und GOSUB Befehlen, die ja auch zu einer bestimmten Zeilennummer verzweigen, wird die Sache schon etwas komplizierter. Der Interpreter ersetzt nämlich beim erstmaligen Abarbeiten eines solchen Befehls die Zeilennummer im Speicher durch die entsprechende Zeilenadresse, um die Abarbeitung im weiteren Programmablauf noch zu beschleunigen (Zeilen ADRESSEN können direkt, ganz ohne oben besprochene Suchroutine angesprungen werden!). Der eigentliche »Knackpunkt« ist nun dieser: Beim Abarbeiten des BASIC-Programms kümmert sich der Interpreter herzlieh wenig um den Offset und die Zeilennummer, solange das Programm LINEAR abläuft (um es einmal locker auszudrücken). Konkreter: Solange der Programmablauf nicht durch viele GOTO-Anwei-sungen zu wilden Sprüngen veranlaßt wird, wird ein Befehl nach dem anderen schön der Reihe nach abgearbeitet. Findet der Interpreter im Speicher eine Zeilenende-Kennung (&00) so »überliest« er einfach die folgenden vier Bytes (sie sind im Moment der Befehlsausführung nicht relevant) und arbeitet den ersten Befehl der neuen BASIC-Zeile ab. Dies wird klar, wenn man sich vor Augen hält, daß folgende zwei kleinen Programme genau das gleiche ausführen: a) b) Auch hätten die Zeilennummern im Programm < b > anders heißen können. Das Resultat bleibt gleich (mit Ausnahme einer kaum meßbaren Differenz in der Ausführungsdauer zwischen Prog. < a > und < b >). Fassen wir also zusammen: Bei der Abarbeitung von linearen BASIC-Programmen nehmen die intern eingetragenen Offsets und Zeilennummern keinerlei Einfluß. Beim Listen von BASIC-Programmen spielen die Offsets eine entscheidende Rolle! Die Konsequenz: Vergrößert man den Offset einer BASIC-Zeile derart, daß der Interpreter beim Listen nicht mehr auf die zwangsläufig nächstfolgende Zeile stößt, sondern erst auf die übernächste (oder sogar noch weiter entfernte), so wird die dazwischenliegende Zeile beim Listen glatt »übersehen«!! Sie wird unlistbar und kann auch durch einen RENUM-Befehl nicht mehr »ans Tageslicht« gebracht werden! Das Programm: Das Programm sollte nach der Eingabe nach 65000 umnummeriert werden. Alle REM-Zeilen können weggelassen werden! Das zu schützende Programm wird danach »dazugemerged«. Gestartet wird das Schutzprogramm mit GOTO 65000 im Direkteingabemodus. Danach wird nach der zu schützenden Zeilennummer gefragt und, falls diese existiert, wird sie dann LIST-geschützt. Das Programm fragt danach nach einer weiteren Zeilennummer, solange, bis der Abbruch durch zweimal ESC eingegeben wird. Das Resultat kann durch LIST gleich begutachtet werden. Es ist jederzeit möglich, das Programm durch GOTO 65000 wieder zu starten. Nach DELETE 65000- steht das modifizierte Programm zum Abspeichern bereit. Die Funktionsweise: Nach Eingabe der Löschzeilennummer wird eine Hauptsuch-schleife aufgerufen. Das Programm sucht ab BASIC-Programm-start den Speicher nach der gewünschten Zeilennummer ab. Dabei »merkt« sich das Programm jeweils den Offset, sowie die Zeilennummer der vorangegangenen Zeile. Wird die zu versteckende Zeile gefunden, wird deren Offset dem zuletzt »gemerkten« Offset dazuaddiert. Der vergrößerte Offset wird jetzt anstelle des alten (gemerkten) Offset zurückgeschrieben. Außerdem erhält die nun unsichtbare Zeile noch die Zeilennummer der vorangegangenen. Weitergehende Informationen: Im allgemeinen kann gesagt werden, daß versteckte Zeilen NICHT durch GOTO- u. -GOSUB angesprungen werden können. Diese Aussage ist aber nur bedingt gültig! Theoretisch ist es möglich, auch versteckte Zeilen anzuspringen, nämlich dann, wenn speicherintern dem GOTO bzw. GOSUB Token eine Zeilenadresse folgt. Dies ist, wie bereits erwähnt, nach einmaligem Programmdurchlauf generell der Fall. Leider wandelt der Interpreter nach Befehlen wie: SAVE und DELETE vor der eigentlichen Funktionsausführung alle Zeilenadressen in Zeilennummern zurück (gilt nicht für SAVE “ . . . " b und SAVE “ . . . “ a)! Damit steht fest, daß nach erneutem Einladen des modifizierten Programms unweigerlich eine Meldung wie: Line does not exist in XXXXX auftauchen wird. Dies wird absolut immer der Fall sein, wenn Sie Datazeilen verstecken und diese später mit einem RESTORE-Befehl direkt ansprechen wollen. Der RESTORE-Befehl bleibt intern immer mit einer Zeilennummer abgespeichert. Die einfachste Lösung auch versteckte Zeilen anzuspringen ist, vor die versteckte Zeile eine belanglose REM-Zeile zu setzen (diese dann natürlich nicht verstecken!), um sie anzuspringen. Das funktioniert ganz tadellos (auch beim RESTORE)!! Wichtig bleibt noch anzumerken, daß das zu schützende Programm in seiner absolut letztgültigen Form vorliegen muß, bevor Sie Zeilen verstecken! Außerdem kann die erste BASIC-Zeile eines jeden Programms nicht auf die hier beschriebene Weise geschützt werden. Natürlich kann man die erste BASIC-Zeile dadurch »unlistbar« machen, daß man die ihre Zeilennummer intern auf &00 setzt, dieses Manöver wird aber durch die einfache Eingabe des RENUM-Befehls wieder zunichte gemacht. Die erste Zeile ist danach wieder sichtbar! (B. Stiller/TM) , CPCAI
|