APPLICATIONSPROGRAMMATION ★ BASIC-Zeilen perfekt verstecken ★

Supersave (CPC Amstrad International)Applications Programmation
★ Ce texte vous est présenté dans sa version originale ★ 
 ★ This text is presented to you in its original version ★ 
 ★ Este texto se presenta en su versión original ★ 
 ★ Dieser Text wird in seiner Originalfassung präsentiert ★ 

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!)

  1. Der BASIC-Speicherbereich beginnt mit einer 0 in Speicherstelle &016F (erster relevanter Wert steht in &0170).
  2. Jede nun folgende BASIC-Zeile beginnt mit einem 2 Byte langen Offset, der angibt, in genau welchem Abstand die nächstfolgende BASIC-Zeile beginnt (Offset = speicherinterne Zeilenlänge).
  3. Die nächsten 2 Byte enthalten die Zeilennummer in hexadezimaler Form.
  4. Nun folgt der eigentliche BASIC-Text im Speicher. Dieser wird aber schon vom Interpreter »übersetzt« abgelegt. D.h. alle BASIC-Befehle erscheinen als eine hexadezimale Tokennummer (teilweise sogar 2 Token). Variablen und Zahlen werden sogar noch gemeiner verschlüsselt. Man spricht in diesem Zusammenhang auch von einer Tokenisierung des Programms.
  5. Eine BASIC-Zeile endet speicherintern mit einer 0.
  6. Direkt darauf folgt die nächste BASIC-Zeile beginnend mit Punkt 2.
  7. Die BASIC-Programm-Endekennung sind drei aufeinanderfolgende Nullen am Schluß der letzten BASIC-Zeile.
  8. Alle 2-Byte-Hexwerte stehen im Low-High-Format im Speicher.

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)
10 PRINT “aaa“: PRINT “bbb“:PRINT “ccc“:END

b)
10 PRINT“aaa“
20 PRINT“bbb“
30 PRINT “ccc“
40 END

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

★ PUBLISHER: CPC Amstrad International
★ YEARE: 1986 , 1987
★ CONFIG: 64K + AMSDOS
★ LANGUAGE:
★ LiCENCE: LISTING
★ COLLECTION: CPC AMSTRAD INTERNATIONAL 1987
★ AUTHOR: B. Stiller
 

★ AMSTRAD CPC ★ DOWNLOAD ★

Type-in/Listing:
» SuperSave    (CPC  Amstrad  International)    GERMANDATE: 2022-08-03
DL: 94
TYPE: ZIP
SiZE: 4Ko
NOTE: 40 Cyls
.HFE: Χ

★ AMSTRAD CPC ★ A voir aussi sur CPCrulez , les sujets suivants pourront vous intéresser...

Lien(s):
» Applications » Dossier Piratage 1985 (CPC Revue)
» Applications » Cours de bidouillage et informations sur les protections Amstrad CPC
» Applications » Déplombage des Fichiers Mallard Basic par Spoke
» Applications » Amstrad Magazine 12 - Dossier Piratage (Amstrad Magazine)
» Applications » Ascii File Protector (Amstrad Action)
» Applications » Protection U.N.C Copieur Pistes HEXAGON
Je participe au site:
» Vous avez des infos personnel, des fichiers que nous ne possédons pas concernent ce programme ?
» Vous avez remarqué une erreur dans ce texte ?
» Aidez-nous à améliorer cette page : en nous contactant via le forum ou par email.

CPCrulez[Content Management System] v8.7-desktop
Page créée en 342 millisecondes et consultée 412 fois

L'Amstrad CPC est une machine 8 bits à base d'un Z80 à 4MHz. Le premier de la gamme fut le CPC 464 en 1984, équipé d'un lecteur de cassettes intégré il se plaçait en concurrent  du Commodore C64 beaucoup plus compliqué à utiliser et plus cher. Ce fut un réel succès et sorti cette même années le CPC 664 équipé d'un lecteur de disquettes trois pouces intégré. Sa vie fut de courte durée puisqu'en 1985 il fut remplacé par le CPC 6128 qui était plus compact, plus soigné et surtout qui avait 128Ko de RAM au lieu de 64Ko.