Erstellt: 17. März 2013 (zuletzt geändert: 3. Juli 2024)

Der Rest

Das Ende ist nah!

C64 Studio, AMCE & TASM

Wir haben es fast geschafft, es sind (mit Ausnahme der undokumentierten OpCodes) nur noch acht Befehle übrig, die wir bisher nicht behandelt haben. Da es sich bei diesen Befehlen (mit Außnahme von einem) nur um Abwandlungen bereits bekannter Befehle handelt, werde ich mich dieses Mal etwas kürzer fassen.

Das Carry-Flag prüfen

Schauen wir uns als Erstes einen weiteren bedingten Sprungbefehl an:

BCS: Branch on Carry Set (springe, wenn das C-Flag gesetzt ist)
BCS relativ ($B0, 2B, 2-4T, <keine>)
Mit dem BCS-Befehl verzweigen wir, sobald das Carry-Flag gesetzt wurde. Wie bei allen bedingten Sprüngen, benötigt der Befehl 2TZ, wenn nicht gesprungen wird, 3TZ bei einem Sprung und wieder 4TZ, falls beim Sprung die Page-Grenze überschritten wird.

Einen Einsatz für BCS können wir z. B. bei folgender Aufgabenstellung finden. Ihr erinnert euch bestimmt, dass wir mit ASL eine Multiplikation mit 2 vornehmen können. Wenn wir dies mit einer größeren Zahl (z. B. 16- oder 32-Bit) machen wollen, müssen wir unser Bit, das links „herausfällt“, ja fürs nächste Byte beachten. Da dieses Bit im Carry-Flag landet, können wir mit BCS darauf prüfen und entsprechend reagieren.

Brrrr, ist das gruselig! Bitte vergesst den Codeschnipsel ganz schnell wieder!
Er soll nur den Einsatz von BCS zeigen, ich hoffe die Kommentare reichen als Erklärung aus.

Wer es dennoch nicht lassen kann, findet hier ein komplettes Beispiel, inkl. einer geänderten Ausgabe für Binärzahlen, damit auch 16-Bit Zahlen angezeigt werden können.

Denkt hier und bei den folgenden Beispielen, beim Turbo Assembler, wieder an die üblichen Probleme: max. Labellänge, keine Unterstriche, nur Kleinschreibung usw.

Rotieren

Das Problem von eben lässt sich viel eleganter lösen, dazu brauchen wir nur einen neuen Befehl:

ROL: ROtate Left (rotiere nach links)
ROL absolut ($2E, 3B, 6T, NZC)
Der ROL-Befehl ähnelt sehr dem ASL. Auch hier wird bitweise nach links verschoben, allerdings wird jetzt von rechts nicht einfach mit einer Null aufgefüllt, sondern mit dem Inhalt des Carry-Flags. Das links herausfallende Bit landet zum Schluß wieder, wie beim ASL, im C-Flag.

ROtate Left
ROtate Left

Wie kann das nun unser 16-Bit shiften vereinfachen? Werft dazu einfach einen Blick auf unser neues Unterprogramm asl_16 .

Na, hab ich zuviel versprochen? Jetzt ist die Funktion doch sehr übersichtlich geworden. Hier nochmal im Detail, wie sie funktioniert:

 

Wer die neue Funktion testen möchte, der kann jetzt mal den Source aufklappen:

Wollt ihr größere Zahlen mit zwei multiplizieren, dann braucht ihr hinter dem ersten ROL, nur weitere für jedes Byte einfügen. Auch die binaryout-Funktion lässt sich jetzt für größere Zahlen (24- / 32-Bit) verwenden. Ihr müsst nur, wie im obigen Beispiel, für das erste Byte zu binaryout springen und für alle folgenden zu binaryout_nextbyte.

 

Auch für den ROL gibt es ein Gegenstück:

ROR: ROtate Right (rotiere nach rechts)
ROR absolut ($6E, 3B, 6T, NZC)
Der ROR-Befehl ähnelt sehr dem LSR. Es findet eine bitweise Verschiebung nach rechts statt, aber auch hier wird diesmal von links nicht mit 0, sondern mit dem C-Flag aufgefüllt. Das rechts herausfallende Bit landet zum Schluß wieder im Carry-Flag.

ROtate Right
ROtate Right

 

Durch eine Kombination von LSR und ROR könnt ihr somit auch größere Zahlen durch zwei Teilen. Ihr müsst hier halt nur beim höchsten Byte beginnen und euch zum niedrigsten durcharbeiten.

Ist euch die bisher nicht verwendete Assemblerdirektive aufgefallen? Wir verwenden hier !word, um bei DWord_32 die benötigten vier Bytes, für unsere 32-Bit-Zahl, zu reservieren. Ihr könntet natürlich auch wieder mit !byte den Platz reservieren. Eine Besonderheit noch: !word legt die 16-Bit im gewohnten LSB/MSB-Format ab. Nach !word $1234, findet ihr im Speicher also $34 $12! Damit lassen sich sehr leicht Adressen im Speicher ablegen.

Da waren es nur noch vier

Kümmern wir uns zunächst um die letzen beiden bedingten Sprünge, die wir noch verwenden können.

BVC: Branch on oVerflow Clear (verzweige, wenn das V-Flag gelöscht ist)
BVC relativ ($50, 2B, 2-4T, <keine>)
Der BVC-Befehl, springt zur angegebenen Adresse, wenn das OVerflow-Flag gelöscht, also 0 ist. Für die Taktzyklen gilt wieder dasselbe, wie bei den anderen bedingten Sprüngen.

BVS: Branch on oVerflow Set (verzweige, wenn das V-Flag gesetzt ist)
BVS relativ ($70, 2B, 2-4T, <keine>)
Hier wird gesprungen, wenn das V-Flag gesetzt, also gleich 1 ist. Taktzyklen, wie gehabt.

 

Da wir gerade beim V-Flag sind, es gibt noch einen Befehl zum Löschen des Flags.

CLV: CLear OVerflow-Flag (V-Flag löschen, auf Null setzen)
CLV implizit ($B8, 1B, 2T, V=0)
Wir können mit CLV das OVerflow-Flag löschen, also auf Null setzen. Aber im Gegensatz zu den anderen Flag-Befehlen, gibt es keinen Befehl zum Setzten des V-Flags! Wenn ihr es dennoch setzen müsst / wollt, bleibt euch nichts Anderes übrig, als entweder eine Rechenoperation auszulösen, die einen Overflow verursacht oder ihr benutzt die bekannten Stackbefehle:

 

Endlich sind wir beim letzten offiziellen Befehl des 6502/6510 angelangt.

Have a break, have an OpCode… 😉

BRK: BReaK (Abbruch / abbrechen, löst einen Software-Interrupt aus)
BRK implizit ($00, 1B, 7T, BI)
Trifft unser Programm auf den BRK-Befehl, wird ein Interrupt ausgelöst. Das ist dem einen oder anderen bestimmt schon mal passiert. Geht z. B. ein RTS daneben, weil der Stack nicht passt, friert entweder der Rechner ein oder man hat Glück und die CPU trifft früher oder später auf ein $00. Dann finden wir einen leeren BS mit der READY.-Meldung links oben, gefolgt von unserem Cursor, vor.
Einfach gesehen, legt BRK den um zwei erhöhten Programmcounter (PC) auf dem Stack ab, setzt das Break-Flag, sichert das Statusregister (SR) auf dem Stack, setzt das Interrupt-Flag und springt zur Adresse, die an $FFFE/$FFFF (IRQ-Vector) zufinden ist.

Im Detail passiert folgendes:

Wenn man BRK für eigene Zwecke, z. B. zum Testen von Programmen nutzen möchte, kann man den Vektor an $0314/$0315 verbiegen. Will man nach dem BRK sein Programm fortsetzen, muss man beachten, dass der PC auf dem Stack um zwei erhöht wurde und somit nicht direkt auf den nächsten Befehl nach dem BRK zeigt! Hier muss man also eine Korrektur vornehmen oder hinter dem BRK ein NOP einfügen. Maschinenmonitorprogramme und Assembler für den C64 nutzen dies häufig, z. B. zeigt SMON nach einem BRK automatisch die Register an. Auch beim Turbo Assembler müsst ihr mit dem Break vorsichtig sein.

Adressierungsarten

Kommen wir zu den letzten Adressierungsarten. Einzig ROL und ROR müssen wir uns jetzt noch mal ansehen. Da die sehr ähnlich sind und wir jetzt am Ende angelangt sind, nur eine kompakte Übersicht:

ROL Akku ($2A, 1B, 2T, NZC)
ROR Akku ($6A, 1B, 2T, NZC)

ROL absolut X-indiziert ($3E, 3B, 7T, NZC)
ROR absolut X-indiziert ($7E, 3B, 7T, NZC)

ROL Zero-Page ($26, 2B, 5T, NZC)
ROR Zero-Page ($66, 2B, 5T, NZC)

ROL Zero-Page X-indiziert ($36, 2B, 6T, NZC)
ROR Zero-Page X-indiziert ($76, 2B, 6T, NZC)

Das Ende, ist erst der Anfang

So, das wars!
Jetzt kennen wir alle Befehle, die der 6502/6510 laut Hersteller beherrscht. Lassen wir die unterschiedlichen Adressierungsarten weg, kommen wir auf nur 56 Befehle. Ihr könnt mit diesen paar Anweisungen also sämtliche Programme, die ihr bisher auf dem C64 gesehen habt, erstellen. Das eine oder andere Programm mag zwar Illigale OpCodes verwenden, aber das sind keine wirklich neuen Befehle, sondern die bewirken in der Regel, dass mehrere Befehle mit einem OpCode ausgelöst werden.

Dies war auch der letzte Beitrag, der auf den Turbo Assembler Rücksicht genommen hat!
Ab jetzt wird nur noch mit dem C64 Studio und ACME entwickelt. Natürlich sind die anderen Beispiele auf diesen Seiten, auch mit dem Turbo Assembler realisierbar. Ich weise aber nicht mehr auf Probleme hin!


Schrott!!Naja...Geht so...Ganz gut...SUPER! (10 Bewertungen | Ø 4,60 von 5 | 92,00%)

Loading...


ZurückWeiter

Ein Gedanke zu „Der Rest“

  1. Hi,
    du schreibst hier jetzt überall “OVerlay-Flag”, aber es ist doch das “OVerflow-Flag”, oder?
    Ansonsten danke für diesen tollen Kurs!

    Grüße

Schreibe einen Kommentar

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

Protected by WP Anti Spam