Schalt mich ein, schalt mich aus

Und oder nicht?

C64 Studio, AMCE & TASM

Die boolschen Befehle werden häufig genutzt, um einzelne Bits zu setzen oder zu löschen. Schaut euch am besten nochmal die Boolsche Algebra an, falls ihr nicht mehr genau vor Augen habt, wie UND und ODER funktionieren.

Wir testen die Boolschen-Befehle in einem neuen, kleinen Beispiel.

Wir werden nun bei den ersten 240 Zeichen auf dem BS jedes zweite invertieren. Wer möchte kann als kleine Übung das Programm ja später so ändern, dass das Programm sich auf den gesamten Bildschirm bezieht. Invertieren bedeutet nichts Anderes, als Zeichen- und Hingrundfarbe zu vertauschen. Wer sich mal Bild-1 und Bild-2 beim Char-ROM ansieht, dem wird jetzt bestimmt etwas auffallen. Das zweite Bild zeigt exakt die gleichen Zeichen, die auch schon auf dem ersten zu sehen sind, nur invertiert. Uns als Binär-Profis sollte bei einem Blick auf die Nummern der einzelnen Zeichen noch etwas ins Auge stechen (Autsch!).

Nehmen wir als Beispiel mal das Zeichen für die Ziffer 7, dies hat in der normalen Darstellung die Nr. 55 / $37 und invertiert die Nr. 183 / $b7 im Zeichensatz.

Jetzt sollte allen klar sein, dass man zum invertierten Zeichen kommt, wenn man einfach das höchste Bit setzt. Das seht ihr ja auch in den beiden Bildern beim Char-ROM, da alle normalen Zeichen im 1. Bild von Nr. 0-127 zu finden sind, die invertierten aber von Nr. 128 bis 255 im zweiten Bild.

Oder

Wir brauchen nun also ein Programm, dass für jedes Zeichen das höchste Bit setzt.

Beim Turbo Assembler könnt ihr keine Unterstriche wie bei loop_ora verwenden, lasst diese einfach weg und schreibt die Labelbezeichnungen direkt zusammen. Denkt auch weiterhin daran, dass die Label dort max. 15 Zeichen lang sein dürfen.

Hier ist nichts Spektakuläres zu sehen, einzig die neue Variable ORAMASK. In unserer Schleife direkt hinter loop_ora laden wir erstmal das Zeichen in den Akku, dass sich an der Adresse SCRENNRAM plus Y-Register (absolute Y-indizierte Adressierung) befindet.

ORA: OR with Accumulator (bitweises ODER mit dem Akku)
ORA Akku ($09, 2B, 2T, NZ)
Hier führen wir jetzt mit ORA eine bitweise ODER-Verknüpfung mit dem Akku und unserer ORAMASK durch. Das Ergebnis landet dann wieder im Akkumulator. Ist das Ergebnis 0, dann wird das Z-Flag gesetzt, sollte Bit-7 auf eins stehen, dann wird das N-Flag gesetzt.
Beim ODER wird ein Bit immer dann zu 1, wenn entweder das erste oder das zweite oder beide beteiligten Bits eine 1 aufweisen:

ORA wird daher verwendet, um gezielt einzelne Bits zu setzen, dazu läßt man in seiner Maske alle Bits, die man nicht ändern möchten auf 0 und setzt nur die Bits auf 1 die man auf jeden Fall auf 1 setzen will. Deshalb ist in unserer Maske nur Bit-7 auf 1 gesetzt worden, alle anderen sind 0.

Im Detail sieht das für unser Zeichen 7, wenn es im Akku liegt, so aus:

Voiala, wir haben das Zeichen 183, das der invertierten Darstellung der entspricht.

Anschließend schreiben wir den geänderten Akku-Inhalt wieder zurück an unsere Position auf dem BS, verringern das Y-Register zweimal fürs übernächste Zeichen und springen solange zu loop_ora zurück, bis das Z-Flag gesetzt ist. Zum Ende gehts zurück ins Basic.

Nach einem Start sollte euer BS ungefähr so aussehen:

Von den ersten 240 Zeichen, jedes 2. invertiert

Nun wollen wir unsere Invertierung wieder rückgängig machen. Dazu verwenden wir diesmal die Möglichkeit aus Basic heraus direkt an die gewünschte Stelle in unserem Programm zuspringen. Vom Prinzip her machen wir das schon bei jedem Programmstart. Unsere Programme beginnen bekanntlich mit der Zeile: 2018 SYS 2062
Diesen SYS-Befehl können wir natürlich auch direkt eingeben, also statt RUN einfach SYS 2062. Ändern wir unser Programm und probieren es mal.

Und

Gebt bitte am Sourcebeginn, hinter ORAMASK , eine neue Variable ein:

Fügt dann hinter unser bisheriges Programm (Ausschnitt ist unten zur Orientierung markiert), die nächsten Zeilen ein:

Etwas irritiert könntet ihr jetzt durch *=$1000 sein. Eigentlich benutzen wir dies ja, um die Startadresse für unser Programm festzulegen (bisher fast immer *=$0801). Auch wenn es nicht wirklich benötigt wird, teilen wir hier dem Assembler mit, dass die nächsten Befehle an der Speicherstelle $1000 oder 4096 dezimal beginnen sollen. Falls ihr neue Adressen angebt, passt besser auf, dass sich diese nicht überschneiden. Das C64 Studio wirft einen Fehler, sollte dies der Fall sein. Bei ACME gibt es eine Warnung, die ja unterdrückt werden können. Der Turbo Assembler nimmt eure Angabe ohne weitere Hinweise / Warnungen an. Wir benutzen dies nur um eine schönere Einsprungadresse für unsere neue Funktion zu erhalten.

AND: AND with Accumulator (bitweises UND mit dem Akku)
AND Akku ($29, 2B, 2T, NZ)
Auch wenn wir das AND schon hatten, wiederhole das hier der Vollständigkeit nochmal. Wir führen jetzt mit AND eine bitweise UND-Verknüpfung mit dem Akku und unserer ANDMASK durch. Das Ergebnis landet dann wieder im Akkumulator. Ist das Ergebnis Null, dann wird das Zero-Flag gesetzt, sollte Bit-7 auf 1 stehen, dann wird das N-Flag gesetzt.
Beim AND wird ein Bit immer dann zu 1, wenn das erste und das zweite Bit eine 1 aufweist:

AND verwenden wir, um gezielt einzelne Bits zu löschen, dazu läßt man in seiner Maske alle Bits, die man nicht ändern möchte auf 1 und setzt nur die Bits auf 0, die man auf jeden Fall löschen will. Daher ist in unserer Maske nur Bit-7 auf 0 gesetzt worden, alle Anderen sind 1.

Und jetzt nochmal für unser invertiertes Zeichen , wenn es im Akku liegt:

Schon haben wir wieder das Zeichen 55, das der normalen Darstellung der 7 entspricht.

Der Rest entspricht dem Block von eben, nur das wir hier einfach mal alle 240 Zeichen anfassen. Es gibt absichtlich nur ein dey, um zu zeigen, dass sich wirklich nur unsere invertierten Zeilen ändern.

Wenn ihr das Progamm nun startet, gibt es zunächst keinen Unterschied zu eben. Gebt jetzt aber mal SYS 4096 ein, drückt RETURN und schon ist die Invertierung verschwunden. Wir springen damit direkt zum Beginn unserer neuen Routine, die ja hinter *=$1000 beginnt. Mit RUN könnt ihr natürlich wieder die Invertierung vornehmen.

Manuell hin- und herschalten.
Exklusives Oder

Abschließend möchten wir jetzt unsere Invertierung invetieren 😉 . Wir wollen also innerhalb der ersten 240 Zeichen alle normalen invertiert darstellen und alle invertierten normal. Dazu könnten wir in unserer Schleife, das in den Akku geladene Zeichen prüfen und dann zur jeweiligen Verknüpfung springen.
Die Routine würde dann so aussehen (bitte am Programmende einfügen!):

Bis auf unsere neue Startadresse *=$2000 ist alles wie gehabt.

BMI: Branch if MInus (springe wenn Minus)
BMI relativ ($30, 2B, 2-4T, <keine>)
Mit BMI verzweigen wir zur angegebenen Adresse, wenn nach der letzten Aktion das „Minuszeichen“ gesetzt ist. Es wird also einfach geprüft, ob das Negativ-Flag = 1 ist. Wie von den anderen bedingten Sprüngen gewohnt, werden 2 Taktzyklen benötigt, wenn nicht gesprungen wird, 3TZ beim Sprung und sogar 4TZ falls der Sprung über eine Pagegrenze geht.
Wir überprüfen hier unser eben in den Akku geladenes Zeichen. Ist es bereits invertiert, dann ist das Bit-7 ja gesetzt und wir springen zu donormal, um die Invertierung aufzuheben, wenn es aktuell nicht invertiert ist invertieren wir es mit dem nächsten Befehl…

Wenn wir invertieren mussten, springen wir nach dem ORA direkt zu charout, müssen wir die Invertierung aufheben, landen wir nach dem BMI bei donormal und löschen mit dem AND unsere Invertierung. Anschließen wird das Zeichen wieder ausgegeben usw. (alles wieder wie eben).

Startet das Programm und es erscheint wieder unsere gestreifte Darstellung. Mit SYS 4096 könnt ihr diese wieder rückgängig machen. Gebt ihr nach dem RUN aber die Startadresse SYS 8192 ein, wird der obere Bereich des Bildschrims inveriert. Bei jedem Aufruf (einfach mit dem Cursor wieder auf den SYS-Befehl gehen und RETURN drücken) ändert sich unsere Anzeige. Probiert das ruhig mal mit der gestreiften und der blanken Darstellung (nach SYS 4096) aus.

OK, dass habe ich jetzt nur eingebaut, um mal den BMI-Befehl zu verwenden und nochmal zu zeigen, dass es viele Lösungsmöglichkeiten gibt. Wir können das Problem auch viel eleganter lösen. Es gibt nämlich einen Befehl, der es uns ermöglicht die Umschaltung zwischen invertiert und normal automatisch vorzunehmen. Gebt die nächsten Zeilen direkt hinter dem Block mit dem BMI-Befehl von eben, also wieder am Ende unseres Sourcecodes ein.

Dieses Mal verzichten wir auf eine neue Startadresse, daher ist es sehr wichtig, dass die vorherige Routine unverändert von euch übernommen wurde, sonst stimmt die im Kommentar ;(8213) angezeigte Startadresse nicht! Der Rest ist mittlerweile kalter Kaffee für uns.

EOR: Exclusiv OR with Accumulator (bitweises exklusives ODER mit dem Akku)
EOR Akku ($49, 2B, 2T, NZ)
Wow, etwas ganz exklusives… EOR arbeitet fast wie ORA. Wir verwenden hier auch unsere ORAMASK und das Ergebnis landet wieder im Akku. Ist das Ergebnis negativ (also Bit-7 gesetzt), dann wird das Negativ-Flag gesetzt, sollte das Ergebnis Null sein, wird das Z-Flag gesetzt.
Beim EOR wird ein Bit nur dann zu 1, wenn ausschließlich das erste oder das zweite Bit eine 1 aufweist:

EOR wird häufig zum Umschalten von einzelnen Bits verwendet. Dazu setzen wir in unserer Maske alle Bits, die Umgeschaltet werden sollen auf 1 und die anderen auf 0.

Für unser Zeichen 7 im Akku, sähe das dann so aus:

Wie ihr seht, schalten wir mit jedem EOR immer das 7-Bit um, die anderen bleiben unverändert.

Wir fabrizieren hier eine Endlosschleife (also obacht beim Start, ggf. vorher speichern), um mal wieder unsere Anfälligkeit für schnelle Bildwechsel zu prüfen.

Zur Sicherheit hier wieder das komplette Programm:

Ein Start zeigt unser Streifenmuster, mit SYS 8213 springt ihr aber in die Endlosschleife mit dem EOR-Befehl und alles flackert…

Endlosschleife mit EOR

Eine Bemerkung am Rande, wenn ihr jetzt einen RESET (z. B. mit ALT+R bei Vice) auslöst und dann SYS 8213 eingebt. Läuft unser Programm wieder an. Also merke, der Speicher wird bei einem RESET nicht gelöscht / initialisiert (jedenfalls nicht alles, Teilbereiche werden schon verändert!).

Wer sich die Boolsche Algebra angesehen hat, der fragt sich jetzt bestimmt wo denn der NOT-Befehl bleibt. Den gibt es zwar unter BASIC, aber nicht im Assembler. Macht noch ein paar Übungen mit den drei boolschen Befehlen und ihr kommt sicher auf die Lösung. Hilfreich könnte es evtl. sein, unser Programm aus dem letzten Beitrag Mit dem Rechner rechnen so anzupassen, dass auch die boolschen Befehle getestet werden können.

Weitere Adressierungsarten

Es folgt wieder die endlos erscheinende Liste, der alternativen Adressierungsarten. Da AND, ORA und EOR identische Adressierungsarten besitzen, werden die jeweils am Stück behandelt.

ORA absolut ($0D, 3B, 4T, NZ)

AND absolut ($2D, 3B, 4T, NZ)

EOR absolut ($4D, 3B, 4T, NZ)
Eine Verknüpfung mit dem Akku und dem Byte, dass an der absoluten Adresse zu finden ist.

 

ORA absolut X-indiziert ($1D, 3B, 4-5T, NZ)

AND absolut X-indiziert ($3D, 3B, 4-5T, NZ)

EOR absolut X-indiziert ($5D, 3B, 4-5T, NZ)
Eine Verknüpfung mit dem Akku und dem Byte, dass an der absoluten Adresse plus dem X-Register zu finden ist. Beim überschreiten einer Page-Grenze wird ein extra Taktzyklus fällig.

 

ORA absolut Y-indiziert ($19, 3B, 4-5T, NZ)

AND absolut Y-indiziert ($39, 3B, 4-5T, NZ)

EOR absolut Y-indiziert ($59, 3B, 4-5T, NZ)
Wie eben, nur mit dem Y-Register.

 

ORA Zero-Page ($05, 2B, 3T, NZ)

AND Zero-Page ($25, 2B, 3T, NZ)

EOR Zero-Page ($45, 2B, 3T, NZ)

ORA Zero-Page X-indiziert ($15, 2B, 4T, NZ)

AND Zero-Page X-indiziert ($35, 2B, 4T, NZ)

EOR Zero-Page X-indiziert ($55, 2B, 4T, NZ)

ORA indirekt X-indiziert ($01, 2B, 6T, NZ)

AND indirekt X-indiziert ($21, 2B, 6T, NZ)

EOR indirekt X-indiziert ($41, 2B, 6T, NZ)

ORA indirekt Y-nach-indiziert ($11, 2B, 5-6T, NZ)

AND indirekt Y-nach-indiziert ($31, 2B, 5-6T, NZ)

EOR indirekt Y-nach-indiziert ($51, 2B, 5-6T, NZ)
Bei Überschreitung einer Page-Grenze wird wieder ein extra Takt benötigt.


Abschließend für alle, die immer noch über den fehlenden NOT-Befehl grübeln, hier ist die Lösung (in unser Programm aus Mit dem Rechner rechnen eingebettet):

Beachtet beim Turbo Assembler wieder, die Besonderheiten, z. B. max. 15 Zeichen für die Label und keine Unterstriche!


Schrott!!Naja...Geht so...Ganz gut...SUPER! (7 Bewertungen | Ø 4,86 von 5 | 97,14%)

Loading...


ZurückWeiter

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

Protected by WP Anti Spam