Assembler-Ecke #17 -------------------- von Tim-Philipp Müller Same procedure as ... - jeder Program- mierer wird die Situation kennen: Das Programm ist fast fertig und läuft auch schon, es fehlen nur noch die kleinen Details, eine schnellere Bildschirm- ausgabe hier, die optimierte Interrupt- routine da und wenn man jetzt dort noch etwas Platz für eine Grafik los- eisen könnte... Sicher, Wunder vollbringen kann kaum einer, aber vielleicht finden Sie im Folgenden ja ein paar Anregungen. Selten benutzt, aber doch nicht ohne sind die Befehle PHP und PLP. PHP sorgt dafür, daß der Inhalt des Statusregisters auf dem Stapel abgelegt wird, PLP bewirkt das Gegenteil und holt sich einen neuen Status vom Stack. Man kann die beiden aber nicht nur bei Debuggern brauchen (die dadurch die Status-Flags sichtbar machen), sondern auch, um Entscheidungen auf später zu vertagen - nach dem Motto: Jetzt vergleichen, später reagieren. Beispiel: .1 LDA ZEICHEN CMP #$9B Return? PHP CMP #27 Esc? BEQ ENDE PLP BEQ NEXT_LINE BNE .1 ENDE PLP RTS ... Das ist natürlich ein unsinniges Beispiel, weil es ohne PHP/PLP einfacher ginge, aber bei komplexeren Routinen wird man die beiden Helfer schnell zu schätzen lernen. Ein weiterer Befehl, der meist auch nur ein verkümmertes Dasein führt, ist BIT. Und das, obwohl er eigentlich ein All- Round-Talent ist, wenn auch nur in absoluter und Zeropage-Adressidrung als BIT $xxxx und BIT $xx. BIT BYTE ... ... setzt das Negativ-Flag (abzufragen mit BPL/BMI), wenn Bit 7 des Inhalts von BYTE gesetzt ist, ... setzt das Overflow-Flag (abzufragen mit BVC/BVS), wenn Bit 6 des Inhalts von BYTE gesetzt ist, ... setzt das Negativ-Flag (abzufragen mit BEQ/BNE), wenn der Inhalt des Akku, AND-Verknüpft mit dem Inhalt von BYTE, null ergibt und ... läßt dabei ,, unverändert. Das wird sich doch wohl irgendwo verwenden lassen, oder? Auch wenn sie nicht gerade besonders elegant aussehen, können die aus BASIC- Zeiten gehaßten DATA-Tabellen ein Assembler-Programm wenn schon nicht vereinfachen, dann wenigstens beschleunigen. Möchte man Sinus/Cosinus-Funktionen verwenden, kommt man an DATA-Wüsten nicht vorbei, ein anderes 'prominentes' Beispiel wird den Nutzen dieser aber verdeutlichen: Mußten Sie schon mal eine Routine schreiben, die x mal 40 rechnet? Wahrscheinlich schon. Wie kann man da denn nun vorgehen, angenommen x bleibt im Bereich von 0-39 (bzw.0-191)? Das einfachste währe natürlich, einfach eine Schleife x-mal zu durchlaufen, die jedesmal 40 addiert: LDA #0 STA ERG STA ERG+1 LDY #x .1 LDA ERG CLC ADC #40 STA ERG BCC .2 INC ERG+1 .2 DEY BNE .1 bei X=191 dürfte das Ganze dann etwas schwerfällig werden... Schneller geht's natürlich mit den Schiebebefehlen, denn 40*x = 32*x + 8*x und 32 und 8 sind ja zufälligerweise Zweierpotenzen. Also zuerst x fünfmal nach rechts geshifted und das Ergebnis gemerkt, dann x dreimal nach rechts shiften und die beiden Resultate addieren. Naja, auch bei größeren x arbeitet die Routine gut, doch ist 40 natürlich eine glücklich gewählte Zahl, bei 31 oder 63 sähe das ganz anders aus... Und nun kann ich mir ja auch noch eine Tabelle zulegen, auch wenn die ein bißchen Speicherfressender ist. Dann brauche ich x nur noch verdoppeln (ASL) und erhalte einen Index. Jetzt braucht man die Werte nur noch auslesen. Die Geschwindigkeit und die Länge eines Programms lassen sich auch schön verbessern, wenn soviele Datenregister wie möglich, die man selbst anlegt, in die Zeropage von $80-$FF legt. Dadurch verkürzt sich ein Befehl um ein Byte (also 33%!), was besonders in doppelt verschachtelten Schleifen und anderen Zeitkritischen Routinen von Vorteil ist. Wer die Fließkommaarithmetik des OS benutzt, muß die entsprechenden Register natürlich freihalten. Außerdem sollten besonders Benutzer des BIBO-Assembler beachten, daß dieser von $80-$CA Daten über den Sourcecode ablegt. Überschreibt man beim Testen dort Register, könnte es sein, das später beim Listen der Quellcode nicht mehr gefunden wird! Diskettenzugriffen über die CIO kann man nur insofern verbessern, als daß Dateien, auf die zugegriffen wird, nicht 'gestückelt' auf der Diskette vorliegen, was besonders dann passiert, wenn oft Dateien gelöscht wurden und dann mit anderen überschrieben wurden. Abhilfe: Alle Dateien auf eine 'frische Disk' umkopieren. Ciao!