von Harald Schönfeld ACHTUNG: In Listingauszügen müssen mit ä+ gekennzeichnete runde Klammern im Editor als eckige Klammern eingegeben werden. Jede Variable, die man in einem QUICK Programm verwenden will, muß zuerst in einem Variablendeklarationsblock de- klariert (angemeldet) werden. Der Deklarationsblock hat den folgenden Aufbau: TYP ( ä+ NAME1,NAME2,... ) ä+ Dieser Block ist vor dem Hauptprogramm- Block (MAIN) und/oder vor Unterpro- gramm-Blöcken (PROC) erlaubt. Vom BASIC her kennen Sie so etwas ähn- liches, denn dort muß man Felder und Strings ebenfalls deklarieren. In QUICK (und allen Sprachen außer BASIC) muß JEDE Variable deklariert werden, egal welcher Typ sie ist. Folgende Typen gibt es: BYTE Eine BYTE-Variable belegt genau ein Byte (8 Bit) im Speicher und kann somit 256 verschiedene Werte annehmen. Im Allgemeinen die Werte 0 bis 255. WORD Dieser Typ belegt 2 Speicherzellen und ist somit 16 Bit groß. Damit lassen sich 65536 Werte darstellen. ARRAY Das ist ein Variablenfeld mit einer Länge von 1 bis 255 Bytes. Größere Fel- der können nicht ohne weiteres in QUICK verwendet werden. Assemblerprogrammierern ist sicher völlig klar, was man mit BYTE oder WORD Variablen macht, dagegen sollten sich BASIC- Programmierer vergegenwärtigen, daß die BASIC- Fließkommavariablen etwas vÖllig anderes sind. BYTE-Variablen können also nur 256 Zu- stände annehmen. Damit eignen sie sich hervorragend für Schleifenzähler und für viele betriebssysteminterne Regis- ter (z.B. Farben, Sounds, Playerpo- sition, Stick, ...). Auch einzelne Zeichen (Chars) kann man in einem BYTE gut abspeichern, denn es gibt ja gerade 256 Zeichen. Will man dagegen größere Rechnungen anstellen, so kommt man mit Werten von 0 bis 255 nicht sehr weit... WORD-Variablen bringen da schon mehr, zumal diese in QUICK auch negative Werte annehmen können. Das hängt davon ab, wie man den Compiler betreibt. Normalerweise laufen QUICK- Programme im UNSIGN- Modus. Damit werden alle WORD- Variablen als positiv, mit Werten von 0 bis 65535 betrachtet. Gibt man jedoch den Befehl SIGN, so werden Vergleiche so durchgeführt, daß WORDs mit den Werten -32768 bis +32767 be- trachtet werden. Dabei hat sich der In- halt der Variablen nicht geändert, son- dern sie werden nur anders interpre- tiert: Das 2er-Komplement Hat man nicht den Befehl SIGN gegeben, so werden Variablen "normal" interpre- tiert, d.h. so wie es die 16 Bits einer WORD-variable angeben. Hat ein WORD z.B. die Bit- Belegung 1000000000000001, so hat sie also den Wert 2^15+2^0 = 32768 + 1 = 32769. Nun kann man sich aber dafür entscheiden, das höchste Bit als "Vorzeichenbit" zu verwenden: Ist es 0, so ist die Zahl positiv, ist es 1, so ist der Wert der Zahl als negativ zu betrachten und zwar nach der Formel Wert = Zahl - 65536. Dazu ein paar Beispiele: BitsÖModus UNSIGN SIGN 0000000000000000 0 0 0000000000000001 1 1 0000000000000011 3 3 0100000000000001 16385 16385 0111111111111111 32767 32767 Sie sehen: Bei Werten, deren höchstes Bit nicht gesetzt ist bleibt alles gleich! 1000000000000000 32768 -32768 1000000000000001 32769 -32767 1000000000000010 32770 -32766 1111111111111110 65534 -2 1111111111111111 65535 -1 Hier schlägt nun die obige Regel zu. Ich möchte nochmal darauf hinweisen, daß es nur eine Interpretationsfrage ist, ob die Zahl negativ ist oder nicht, denn Rechnen kann man mit beiden gleich: 0000000000000001 1 1 + 1000000000000000 + 16384 + -32768 = 1000000000000001 = 16385 = -32767 Das paßt in beiden Fällen. Und auch das Folgende geht gut: 0111111111111111 16383 16383 + 1111111111111111 + 65535 + -1 =(1)0111111111111110 = 16382 = 16382 Sie sehen, das Ergebnis ist gleich, egal ob man 65535 oder "-1" dazuzählt, denn durch den überlauf in der (nicht vorhandenen!) 17.Stelle ergibt sich das gleiche Resultat. Es bleibt also Ihnen überlassen, ob Sie einen Vergleich - und nur da ist die Frage "2er-Komplement oder nicht ?" entscheidend - im SIGN oder UNSIGN-Mo- dus durchführen. Bei Berechnungen spielt es keine Rolle. Der Befehl SIGN oder UNSIGN kann beliebig oft in einem QUICK-Programm verwendet werden, wie man es eben gerade braucht. Dazu ein Beispielprogramm: WORD ( ä+ W1,W2 ) ä+ MAIN W1=1 W2=65535 UNSIGN IF W1>W2 PRINT("W1 IST GROESSER") ELSE PRINT("W2 IST GROESSER") ENDIF SIGN IF W1>W2 PRINT("W1 IST GROESSER") ELSE PRINT("W2 IST GROESSER") ENDIF ENDMAIN Nun, wir haben uns zwar noch nicht mit IF-ELSE-ENDIF und PRINT befaßt, aber ich denke das ist schon verständlich. Wichtg ist hier: Was printet das Programm denn nun ? Im UNSIGN-Modus ist 1 natürlich kleiner als 65535, im SIGN-Modus ist 1 aber größer als -1. Also: W2 IST GROESSER W1 IST GROESSER Der Inhalt hat sich nicht geändert, aber durch die Interpretationsänderung hat sich der WERT der Variable geän- dert. Nun, für BASIC-Programmierer ist das vielleicht schwer verdauliche Kost, denn im BASIC hat eine Variable immer den gleichen Wert. In QUICK kann man das zwar selbst frei gestalten, es hat sich aber herausgestellt, daß man so- wieso meist im UNSIGN-Modus arbeitet, denn es ist ja immer erlaubt zu schreiben: W2=-1 egal, in welchem Modus man ist und auch die Berechnungen klappen in jedem Modus. Erst bei Vergleichen muß man aufpassen. So, soviel zu diesem trockenen, aber wichtigen Thema. WORD Variablen im UNSIGN-modus eignen sich hervorragend für Speicheradres- sierungen, denn sie haben den gleichen Umfang (0 bis 65535) wie der Speicher. Mit den ARRAYs beschäftigen wir uns das nächste Mal, und machen jetzt gleich mit dem interessanten Gebiet der Glo- balen und Lokalen Variablen weiter: Globale Variablen Wird eine Variable im Variablenblock vor MAIN deklariert, so ist sie "Glo- bal", d.h. sie ist in allen Programm- teilen unter diesem Namen bekannt und verwendbar. Lokale Variablen Wird eine Variable im Variablenblock zu Beginn eines Unterprogramms deklariert, so ist sie "Lokal", d.h. sie ist nur in diesem Unterprogramm bekannt. In an- deren Programmteilen kann auf sie nicht zugegriffen werden. Hat eine lokale Variable den gleichen wie eine globale, so wird die lokale im Unterprogramm verwendet. Welchen Sinn macht das Ganze? 1. "Unwichtige" Variablen, die für den Programmablauf nicht weiter von Bedeu- tung sind, werden so "versteckt" und stören nicht weiter. 2. Es ist möglich gleiche Namen für verschiedene Variablen zu verwenden. Man kann sich in mehreren Unterpro- grammen I,J und K für Zählschleifen definieren und braucht keine Sorgen zu haben, daß sich die Schleifen ins Gehege kommen, denn jede Variable ist nur in "Ihrem" Unterprogramm am Zug. 3. Man kann Routinen schreiben die nur lokale Variablen benutzen, so daß sie mit jedem Hauptprogramm laufen, egal welche Variablen in dem deklariert sind. 4. Man kann Unterprogramm- Bibliotheken anlegen, die Ihre eigenen Variablen haben, und es ist kein Problem, wenn ein Variablennamen in verschiedenen Bibliotheksroutinen vorkommt, denn er ist ja in jeder ein anderer... Es gibt dabei 3 verschiedene Arten von lokalen Variablen: LOCAL Ohne Bezug zur Umgebung. IN Auch lokal, wird aber ans Unterprogramm vom rufenden Programm "übergeben". OUT Auch lokal, wird aber vom Unterprogramm an dessen Ende ans rufende Programm zurückgegeben. Was es damit auf sich hat, sehen wir wenn wir uns mit den Unterprogramm- Blöcken beschäftigen.