Tips & Tricks für Programmierer

Moderne Assembler - wie beispielsweise der »GFA-Assembler« - optimieren Ihre Programme weitgehend automatisch - Denkfehler müssen Sie aber selbst ausschließen.

Assembleroptimierung

Kein Assembler für den ST entbindet Sie von der Pflicht, schon beim Listing für die Effizienz des Codes zu sorgen. Im folgenden finden Sie einige Beispiele dafür:
Grundsätzlich sollten Sie »short« adressieren, wo immer sich dazu Gelegenheit bietet. Das heißt, mit nur 16 Bit Adreßbreite auf effektive Adressen zuzugreifen. Das spart Programmspeicher und beim 68000er auch Zeit. PC-relative Zugriffe auf Speicherzellen sind ebenfalls wesentlich schneller und kürzer als absolute Zugriffe. Wenn Sie beispielsweise den Befehl »pea label« schreiben, so muß der Prozessor zunächst das erste »Word« (= 16 Bit) der »Label«-Adresse laden, dann das zweite und beide nacheinander auf den Stack legen. Zusätzlich reloziert das Betriebssystem der STs vor jedem Programmstart die Adresse des »Labels«, denn das Programm kann ja theoretisch an jeder Stelle des Speichers liegen. Dazu ist vom erheblichen Verwaltungsaufwand einmal abgesehen - auch eine zusätzliche Reloziertabelle notwendig, die der Assembler dem Programm beifügt und den Quellcode damit unnötig vergrößert. Beim Befehl »pea label(PC)« hingegen lädt der Prozessor das »Label« nur als Offset, d.h. als 16-Bit-Wert, den er zum »PC« (Program Counter, die Adresse des momentan bearbeiteten Befehls) addiert. Anschließend speichert er das Ergebnis auf dem Stack. So erzielen Sie den gleichen Effekt schneller und kürzen

Vorsicht ist allerdings geboten, wenn Sie Objektfiles erzeugen. Mehrere Objektfiles werden nämlich normalerweise vorn Linker zu einem Hauptprogramm »zusammengelinkt«, also miteinander verbunden. Dabei »zerpflückt« der Linker die einzelnen Segmente der Objektdateien und setzt sie an völlig neuen Stellen wieder zusammen. Normalerweise hat das auch gar keine Folgen. Wenn Sie jedoch PC-relativ über eine Segmentgrenze zugreifen (beispielsweise vom »TEXT«Segment ins »BSS«), dann liegt die Speicherzelle, die Sie ansprechen wollten, gar nicht mehr an der Stelle, wo Sie zum Assemblierzeitpunkt lag. Das führt in der Regel zur Zerstörung Ihres Programmcodes. Assembler sollten deshalb in der Lage sein, vor dem Speichern von Objektdateien auf solche Fehler hinzuweisen. Leider ist »TurboAss« unseres Wissens der einzige Assembler, der diesbezüglich Warnungen ausgibt. So bleibt Ihnen beim Entwerfen von Objektdateien mit anderen Assemblern nichts anderes übrig, als selbst peinlich auf Fehler zu achten. Meist ist es hilfreich, wenn man das »TEXT«- und »DATA«-Segment zu einem einzigen »TEXT«-Segment zusammenlegt (das Betriebssystem unterscheidet sie ohnehin nicht) und aufs »BSS« nicht PC-relativ zugreift.

Unterprogramme

Bei Durchsicht eingesandter Programme fallen uns öfters die abenteuerlichsten Konstruktionen für den Aufruf von Systemroutinen auf. Ein exzellentes Beispiel, wie man's eigentlich nicht machen sollte, war der »Floppy-Speeder« [1]. Das Programm setzt ein einziges Bit im Speicher - und ruft dafür sage und schreibe sechsmal OS-Routinen auf. Darunter dreimal die GEMDOS-Funktion Nr. 9 »Cconws()«. Da der ST seine Betriebssystemfunktionen leider sehr uneffektiv aufruft (man vergleiche mit den LineA-Befehlen des Apple Macintosh), fällt so völlig überflüssiger Verwaltungsaufwand an. Deshalb sollten Sie oft benutzte OS-Aufrufe stets als Unterprogramme verfassen, die sie dann per »bra unterprogramm« oder »bra.s unterprogramm« anspringen lassen. Das ist zwar etwas langsamer, aber langsam sind OS-Aufrufe auf dem ST eigentlich grundsätzlich.

Mauszeiger

Kein Programm darf den Mauszeiger des Ataris während eines Lese- oder Schreibzugriffs auf Massenspeicher abschalten. Er muß stets sichtbar bleiben. Sonst kann es Ihnen passieren, daß Sie eine eventuell auftretende GEM-Fehlermeldung ohne Mauszeiger oder »Nerver Forbud« [2] nur mit Glück und heftigem Fluchen verlassen können. Stets darauf achten, daß der Mauszeiger auch bei auftretenden Fehlern im laufenden Programm sichtbar bleibt.

Unpräzises CPU-Timing

Spätestens seit dem Erscheinen von 16-MHz-Beschleunigerkarten wie der PAK-68 oder den mittlerweile in den verschiedensten Ausführungen erhältlichen Zusätzen für die STs dürfte auch dem letzten Programmierer klar sein, daß man sich nicht mehr auf exaktes CPU-Timing verlassen kann. Die 16-MHz-Karten verdoppeln zwar die Rechengeschwindigkeit innerhalb des 68000er Zentralprozessors, wie hoch die tatsächliche Beschleunigung aber letztendlich ist, hängt entscheidend davon ab, wie schnell Zugriffe aufs RAM erfolgen können. Das nämlich ist weiterhin mit 8 MHz getaktet. Um auch diese Zugriffe nachträglich zu beschleunigen, bieten die Hersteller solcher Karten verschiedene Cache-Speicher an. Allerdings steuern diese Caches die Elektronik ihrerseits wieder sehr unterschiedlich. Dadurch kann niemand mehr garantieren, daß ein »NOP«-Befehl auch wirklich vier Taktzyklen von jeweils 8 MHz = 0.0000005 Sekunden benötigt. Noch komplizierter wird es beim Einsatz neuer Prozessoren wie dem 68020 in der PAK-68. Dieser Prozessor verwandelt den ST - der ja ein »Sixteen/Thirtytwo« ist - schon beinahe in einen echten 32-Bit-Rechner, ohne jedoch den vollen Adreßbereich ansprechen zu können. Beim TT schließlich gerät ein solcher Versuch zu einem vollends aussichtslosen Unterfangen. Diese Unterschiede beim CPU-Timing sind auch der eigentliche Grund, warum kaum ein ST-Spielprogramm auf dem TT laufen wird: Der TT selbst kann eigentlich gar nichts dafür.

Literatur:
[1] A. Hierstetter, »Die Systemvariablen des Atari ST«, ST-Magazin 5/90, Seiten 24ff., Markt&Technik Verlag.
[2] L. Prüßner, »Tips zu Assembler-Optimierungen«, ST-Magazin 8/90, Seiten 61ff., Markt& Technik Verlag.


Laurenz Prüßner
Aus: ST-Magazin 10 / 1990, Seite

Links

Copyright-Bestimmungen: siehe Über diese Seite