Schalt mich ein, schalt mich aus

Für diesen Beitrag wurde das CBM prg Studio verwendet.
weitersagen ...
Tweet about this on TwitterShare on FacebookShare on Google+Share on LinkedIn

CBM prg StudioUnd oder nicht?

Die boolschen Befehle werden häufig genutzt, um einzelne Bits zu setzen oder zu löschen. Schaut euch bitte 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 mal das Zeichen ‚7‚, dies hat in der ‘normalen‚ Darstellung die Nr. 55 und invertiert die Nr. 183 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, 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.

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

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 ‚7‚ 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
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:

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.

 

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. Das CBM prg Studio wirft euch übrigens eine Fehlermeldung aus, falls es zu einer Überschneidung der Speicherbereiche kommt. Wir benutzen das 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öchten 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 ‚7‚, 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 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 und 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.

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 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 das 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.

Diesmal 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
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.


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):


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

Loading...


<<<zurück | weiter>>>

weitersagen ...
Tweet about this on TwitterShare on FacebookShare on Google+Share on LinkedIn

Schreibe einen Kommentar

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

Protected by WP Anti Spam