Bisher geheimgehalten, jetzt veröffentlicht: 30 neue Befehle in Ataris Super-Basic (Teil 1)
Die Sensation ist perfekt: 30 bislang unbekannte Befehle, Funktionen und Systemvariablen verstecken sich im Omikron-Basic. Ataris offizielle Programmiersprache zum Atari ST — kaum zu glauben — birgt zweieinhalb Dutzend Kraftpakete, die bisher an keiner Stelle dokumentiert und nur wenigen Insidern bekannt waren. Die erste Hälfte stellen wir Ihnen in diesem Beitrag vor, die zweite in der kommenden Ausgabe. Außerdem finden Sie alle Nachzügler-Befehle bereits auf den Omikron-Basic-Referenzkarten in dieser und der letzten Ausgabe.
VERSION (Systemvariable)
In einem guten Entwicklungssystem können Sie die Versionsnummer abfragen. Omikron-Basic benutzt dazu die Systemvariable »VERSION«. Der Wert dieser Variable entspricht der Versionsnummer des Basics, multipliziert mit 100. Bei Version 3.00 gibt »PRINT VERSION« den Wert 300 aus. Bei Version 3.0 ist »VERSION« nicht implementiert. Demnach ergibt die obige Ausgabe den Wert 0. Beispielsweise testet die neue GEMLIB in der Prozedur »Appl_Init« mit der Anweisung »IF VERSION < 300 THEN«, ob die benutzte Basic-Version die Library verwenden darf. Es sind einige Compiler der Version 3.00 auf dem Markt, die »VERSION« nicht korrekt compilieren. Raubkopierer haben Pech gehabt, registrierte Benutzer bekommen bei Omikron ein Update.
LIBRARY (Befehl)
LIBRARY CODE
UNLIST
Die Firma Omikron sieht ihr Basic als Entwicklungssystem, das professionellen Ansprüchen genügt. Dazu gehört auch die Verfügbarkeit von Libraries zu verschiedenen Themengebieten. Seit der Version 3.00 des Basics unterscheiden wir zwei Arten von Libraries: Omikron- und Nicht-Omikron-Libraries. Libraries, die unabhängig vom Basic entstanden sind, laden und speichern Sie als ASCII-Textblock. Anders ist dies bei Omikron-Libraries. Diese sind in einem Token-Format gespeichert und lassen sich sehr schnell nachladen.
Die Sache mit den Omikron-Libraries hat einen Haken: Um eine Library im Token-Format zu speichern, sind Änderungen im Token-Format sowie ein Vorspann (Header) erforderlich. Da dessen Aufbau nur den Programmautoren selbst bekannt ist, können Sie bisher aus Ihrer selbstentwickelten Funktionensammlung keine Token-Library machen. Ihnen bleibt nur die alte Methode über die ASCII-Textblöcke.
Der Befehl »LIBRARY < name >, < filename >« lädt die Library mit dem Namen < name >. < filename > gibt den Zugriffspfad und Dateinamen der Library an. »LIBRARY« ergänzt das Programm nur um die Library, wenn diese noch nicht im Arbeitsspeicher ist. Beispielsweise lädt das Basic mit dem Befehl »LIBRARY Gem, "A:\GEM.LIB"« die GEMLIB zu Ihrem Programm.
Der Editor zeigt den Programmtext der Library nicht an. Sie ist »LIST«-geschützt.
Das Basic kennt zwei weitere Befehle zur Library-Verwaltung: »LIBRARY CODE« und »UNLIST«. Diese beiden Befehle erzeugt die Library. »UNLIST« können Sie getrost links liegen lassen, da Sie mit diesem Befehl wahrscheinlich nie in Kontakt kommen. Den Befehl »LIBRARY CODE« fügt die Library in Ihr Programm ein, wenn Sie diese geladen haben. Als Eingabe lehnt der Tokenizer die Befehle »LIBRARY CODE« und »UNLIST« ab. Zeilen mit diesen Befehlen dürfen Sie nicht editieren. Tun Sie es dennoch, meldet der Editor einen »Syntax Error«. Die Library ist dadurch aus dem Arbeitsspeicher gelöscht. In diesem Fall hilft nur noch eins: Entfernen Sie die fehlerhafte »LIBRARY CODE«-Zeile und starten Sie das Programm mit »RUN« neu. Der »LIBRARY«-Befehl lädt die gewünschte Bibliothek dann erneut.
Mit den 30 verborgenen Schätzen des Omikron-Basic starten wir gleichzeitig ein neues Forum im ST-Magazin: Die Basic-Ecke. Diese ständige Einrichtung begleitet Sie — egal ob GFA- oder Omikron-Basic-Fan — in Zukunft Monat für Monat.
Forum heißt: Immer wenn Sie Fragen zu einer dieser beiden Programmiersprachen haben, sind wir für Sie da. Auch wenn Sie beim Programmieren hängenbleiben: Schreiben Sie uns.
Eine Auswahl solcher Fragen stellen wir Ihnen von Mal zu Mal an dieser Stelle vor. Entweder mit Antwort, oder aber — in besonders kniffligen Fällen — als Knobelei für alle Leser.
Außerdem werden wir interessante Tricks, Routinen, News und Entwicklungen besondere Aufmerksamkeit schenken. Dazu ist Ihre Beteiligung gefragt. Wann immer Sie programmierend »Neuland erforschen« oder Ihnen ein Basic-Befehl »spanisch« vorkommt oder Sie gar »böhmische Dörfer« zwischen ABS und XOR entdecken, schreiben Sie (leicht verständlich und für jedermann nachvollziehbar) an:
Markt & Technik Verlag AG Redaktion ST-Magazin Stichwort »Basic-Ecke« Hans-Pinsel-Straße 2 8013 Haar bei München
Die Compilerversion 3.01 compiliert nur Prozeduren und Funktionen aus der Library, die Ihr Programm auch verwendet. Unbenutzten Ballast compiliert sie nicht mit.
INLINE (Befehl)
Inline-Code ist die schnellste und einfachste Integration von Maschinencode in ein Programm einer höheren Programmiersprache. Maschinensprache-Routinen werden in den Programmtext eingebunden und unverändert ausgeführt. Der Aufruf über »CALL« oder ähnliche Befehle ist nicht nötig.
Mit dem Befehl »INLINE " < hex-codes > "« integrieren Sie Inline-Code in ein Basic-Programm. Die Zeichenkette < hex-codes > enthält den hexadezimalen Code des assemblierten Programms.
Der Basic-Editor erlaubt Ihnen keine direkte Eingabe von Assembler-Mnemonics, sondern nur den assemblierten Code. Ein sinnvoller Arbeitsablauf sieht folgendermaßen aus: Mit einem Assembler entwickeln Sie die Maschinensprache-Routine und generieren den Maschinencode. Diesen geben Sie bei »INLINE« in Hexadezimalzahlen an.
Sie müssen alle Maschinencodes einer Routine in einem einzigen »INLINE«-Befehl angeben. Streng nach dem Sprichwort »Das Ganze ist mehr als die Summe der Teile« dürfen Sie die Maschinensprache-Routine nicht ohne Änderungen auf zwei aufeinanderfolgende »IN-LINE«-Befehle verteilen.
Hinter »INLINE« können Sie soviel Codebytes angeben wie in eine Editorzeile passen. Mittlerweile können Sie mit »INLINE < stringvariable > « die Zeichenkette auch in einer String-variablen übergeben. < stringvariable > darf maximal 252 Codebyte enthalten, da der Basic-interne Puffer nicht größer ist.
Die Unterteilung der Zeichenkette < hex-codes > oder der Stringvariablen durch Leeroder andere Formatzeichen ist unzulässig.
Eine Frage betrifft die Verträglichkeit der Maschinensprache-Routine mit dem Basic-Interpreter und dem Compiler. Im Interpreter dürfen Sie alle Register benutzen. In compilierten Programmen nur die Register »D0« bis »D5« und »A0« bis »A2«. Daraus folgt, daß Sie auf die Register »D6«, »D7« und »A3« bis »A7« verzichten müssen.
Im compilierten Programm treten Schwierigkeiten auf, wenn Sie Inline-Code und Multitasking-Befehle beziehungsweise Interrupt-Routinen verwenden. Abhilfe schafft das Compiler-Steuerwort »Multitasking_Between_Statements«, denn es verhindert Unterbrechungen während der Inline-Code-Abarbeitung.
Das folgende Assemblerprogramm ruft den LINE-A-Emulator des TOS auf und zeichnet eine Linie mit den Endpunkten 0,0 und 319,199. Hinter den Befehlen sind die Maschinencodes angegeben.
dc.w $a000 ; A000 LINE-A initialisieren
move #0,38(a0) ; 317C00000026 x1-Koordinate
move #0,40(a0) ; 317C00000028 y1-Koordinate
move #319,42(a0) ; 317C013F002A x2-Koordinate
move #199,44(a0) ; 317C00C8002C y2-Koordinate
dc.w $a003 ; A003 LINE-A Linie zeichnen
Diese Routine integrieren Sie mit
INLINE "A000317C0000026317C00000028317C 013F002A317C00C8002CA003 "
in ein Basic-Programm. Erlaubt ist auch
A$=#A00O317C0000026317C0000 0028317C013F002A317C00C8002CA003"
INLINE A$
Nicht zulässig sind dagegen Ausdrücke wie beispielsweise
INLINE "A000 317000000026 317C00000028 317C013F002A 317C00C8002C A003"
oder
INLINE "A000317C000000 26317000000028": INLINE "317C013F002A317C00C800 2CA003"< <
BRK (Befehl)
Der 68000er des Atari ST reagiert auf einen unbekannten Befehlscode mit der Ausführung einer Illegal-Exceptionroutine. Im Basic erzeugen Sie einen illegalen Befehl mit »BRK«. Es wird als »ILLEGAL«-Mnemonic compiliert und löst die Ausnahmeverarbeitung aus.
COMPILER (Befehl)
Omikron hat einige Befehle in den Befehlssatz des Basics aufgenommen, die die Compilierung vereinfachen. Diese Befehle sind in erster Linie für die Besitzer des Compilers gedacht.
Bei den alten Basic-Versionen konnten Sie die Compiler-Steuerworte nur mit dem Aufruf von »Leerprozeduren« setzen. Ab Version 3.00 gibt es den Befehl »COMPILER < stringausdruck >«. Für < stringausdruck > geben Sie die gewünschten Steuerworte an. Mehrere Steuerworte trennen Sie durch Strichpunkte, etwa »COMPILER "Trace_On; Multitasking_Between_Statements"«. Die Unterstriche in den Steuerworten dürfen Sie auch durch Leerzeichen ersetzen.
COMPILER ON/OFF (Befehl)
Außerdem kennt die Version 3.00 die Befehle »COMPILER ON« und »COMPILER OFF«. Alle Befehle zwischen »COMPILER OFF« und »COMPILER ON« werden nicht compiliert. Diese Art der Compilersteuerung sollten Sie erst ab Version 3.01 des Compilers nutzen, denn die Version 3.00 arbeitet bei geschachtelten Strukturen nicht immer korrekt.
COMPILER (Systemvariable)
Interessant ist auch die Frage, ob ein laufendes Basic-Programm vom Basic interpretiert wird oder als compiliertes Programm selbständig läuft. Sie können es dann compiliert anders reagieren lassen als interpretiert. So können Sie beispielsweise beim Compilat die Abbruchmöglichkeit mit < Control C > sperren, wogegen Sie im Interpreter abbrechen dürfen. Auch unerwünschte Geschwindigkeitsdifferenzen lassen sich über Warteschleifen abfangen.
Diese Abfrage unterstützt die Systemvariable »COMPILER«. Sie enthält den Wert 0, wenn das laufende Programm interpretiert wird. Arbeitet es als eigenständiges Programm, dann enthält »COMPILER« den Wert -1. Im Prinzip ist »COMPILER« eine Erweiterung des Befehlssatzes um die Zeile auf Seite 12 des Compiler-Handbuches. Diese Zeile ist nicht zulässig, da Sie »COMPILER« keinen Wert zuweisen dürfen.
Eine Einschränkung betrifft die Systemvariable »COMPILER«. Da sie in Version 3.00 von der Auflistungs-Routine des Basic-Interpreters nicht korrekt erkannt wird, sind Ausdrücke wie »IF NOT COMPILER THEN« oder »IF COMPILER = 0 THEN« unzulässig. Erlaubt ist nur die Abfrage »IF COMPILER THEN«.
RESERVED(x) (Funktion)
Omikron-Basic verwaltet intern einen reservierten Speicherbereich, in dem Basic-interne Werte und Variablen von Libraries gespeichert sind. Die Adresse des reservierten Speicherbereiches ermitteln Sie mit der Funktion »RESERVED( < index >)«. Der Rückgabewert ist die Adresse des < index >-ten Bytes. Den Speicherblock beschreiben Sie mit den »xPOKE«-Befehlen. Mit den »xPEEK«-Befehlen lesen Sie einen Teil des Speicherblock aus.
Der reservierte Speicherbereich ist nicht für die Nutzung in eigenen Programmen gedacht. Wenn Ihr Programm einen Teil des Speicherblockes zur Speicherung von Werten benutzen will, müssen Sie sich mit Omikron in Verbindung setzen. Nur dadurch ist gewährleistet, daß verschiedene Programme und Libraries nicht kollidieren.
Folgende Teile des Speicherblockes sind bereits von Omikron vergeben. Sie dürfen sie für den angegebenen Zweck verwenden:
0 Dieses Langwort enthält nach dem Rücksprung aus einer Maschinensprache-Routine, die Sie mit »CALL« aufgerufen haben, den Inhalt des Datenregisters D0. Mit »LPEEK (RESERVED(0))« ermitteln Sie den 32-Bit-Wert von D0.
4 Eine 1 in diesem Speicherbyte unterbricht ein compiliertes »INPUT USING« bei einem Interrupt sofort. »INPUT USING« liefert in diesem Fall den Rückgabewert -3. Dazu muß das Compiler-Steuerwort »Multitasking_Always« aktiv sein.
Vorwiegend ist der reservierte Speicherbereich für Variablen von Libraries gedacht. Beispielsweise verwenden die GEMLIB- und die Finanzmathematik-Library diesen Speicherbereich für lokale Werte der Library. (mr)