Erstellt: 24. März 2013 (zuletzt geändert: 7. Januar 2018)

Alles illegal!

Die illegalen OpCodes des C64

C64 Studio & AMCE

Da sind wir also, bei den „sagenumwobenen“ illegalen OpCodes. Eigentlich ist dies kein Thema für Einsteiger, aber ich möchte in den Grundlagen einmal alle Befehle erwähnt haben. Als erstes sollte ich aber darauf hinweisen und warnen (das mache ich hier noch häufiger), dass die hier aufgeführten Befehle teilweise nicht ganz unproblematisch sind. Ihr solltet sie also mit Bedacht einsetzen.

Wir haben jetzt alle 56 Befehle des Prozessors kennengelernt, die offiziell zur Verfügung stehen. Wie wir aber wissen, besitzt der C64 einen 8-Bit-Prozessor, somit sind theoretisch 256 unterschiedliche Befehle möglich. Bei unseren 56 bisherigen kommen wir, wenn man die unterschiedlichen Adressierungsarten mit einbezieht, auf 151 verwendete Bytes. Bleiben also noch 105 mögliche Befehle übrig. Dabei handelt es sich meistens um eine Kombination aus mehreren offiziellen Befehlen (z. B. erst ein ASL und dann ein ORA). Diese mehr oder weniger sinnvollen Befehle, werden häufig als ‚illegal‘, ‚extra‘ oder ‚undocumented‘ bezeichnet. Einige Befehle haben sogar mehrere OpCodes, obwohl es sich immer um denselben Befehl handelt, dort wird also keine andere Adressierungsart verwendet.

Hardware-Exkurs: Wieso gibt es solche OpCodes überhaupt?

Befehlsdekodierung

Ich will hier nicht wirklich in die Details gehen, es soll nur eine kurze oberflächliche Erklärung werden.
Der 6510/6502 benutzt keine MicrocodesinfoInfoDie Befehle der CPU sind nicht fest verdrahtet, wie z. B. bei RISC-Prozessoren, sondern in einem ROM gespeichert., um die Befehle zu dekodieren, wie andere CPUs. Das „Instruction-Register“ und der Zyklus aus der „Timing Generation Logic“ werden im „Decode ROM“ zusammengefasst. Diese besteht aus 130 Zeilen zu je 21 Bits. Jede Zeile enthält nun Bit-Muster, die zur Identifikation der Befehle dienen. Dabei wird festgelegt, welche Bits im Muster 0 und welche 1 sein müssen und bei welchem Zyklus das stattfindet. Trifft ein Muster zu, so liefert die Zeile eine 1. Jeder Befehl ist hier also mit einem Bit-Muster hinterlegt, verwendet man einen illegalen OpCode, dann kann dieser auch dekodiert werden. Aber durch die ungeplanten Bit-Muster ist es nun möglich, dass mehrere Zeilen eine 1 liefern und wir so die eben erwähnte Kombination von bekannten Befehlen erhalten.

 

Wie kann man die Befehle nun verwenden?

Zunächst mal ist wichtig, dass das System auf dem das Programm laufen soll, diese Befehle versteht. Bei einem echten C64 ist das der Fall, auch die meisten Emulatoren können diese Befehle umsetzen, aber das muss nicht immer so sein.
Für uns als Programmierer ist es natürlich am schönsten, wenn unser Assembler diese Befehle kennt. Auch für die illegalen-Befehle gibt es Mnemonics, da diese aber nicht offiziell sind, gibt es teilweise unterschiedlichen Namen für einen Befehl. Hier muss man ggf. schauen, welche der verwendete Assembler versteht. Sollte der Assembler mit den Befehlen nichts anfangen können, dann müsst ihr wohl oder übel die gewünschten Befehle direkt als Bytes eingeben. Je nach Assembler ist es evtl. auch noch möglich sich eigene Macros für die Befehle zu bauen. Das C64 Studio versteht einen Großteil der hier erklärten Befehle, ACME einige weniger. Beim Einsatz von ACME müsst ihr als CPU-Typ außerdem 6510 angeben, sonst gibt es Fehler bei der Assemblierung. Fügt zu Beginn einfach ein !cpu 6510 in den Quellcode ein. Beim C64 Studio könnt ihr dies zur Sicherheit auch machen.

Der Turbo Assembler kennt die Befehle nicht, dort müsst ihr mit .byte arbeiten.

Die Befehle sind zum Teil echt strange, ich versuche erst gar nicht sinnvolle Beispiele anzubieten. Meiner Meinung nach sollte man diese Befehle nur im äußersten Notfall einsetzen, z. B. wenn sie dringend benötigten Platz sparen oder in einer zeitkritischen Routine einen Vorteil bringen.

Diese Liste wurde anhand der Infos auf verschiedenen Internetseiten und mit dem Buch „The Complete Commodore Inner Space Anthology“ erstellt. Ich bin trotzdem nicht ganz sicher, ob alles stimmt (z. B. habe ich bei den Taktzyklen nicht immer einen Hinweis darauf gefunden, ob und wie sich eine Überschreitung der Page-Grenze auswirkt).

Los gehts…

Genug der Vorrede, werfen wir endlich einen Blick auf die letzten Befehle des C64:

SLO bzw. ASO
slo $082d

SLO: ASL+ORA (alternatives Mnemonic: ASO)
SLO absolut ($0F, 3B, 6T, NZC)
SLO kombiniert ein ASL mit einem ORA. Dabei wird das, über die Adressierung zufindene Byte zunächst per ASL bitweise nach links verschoben und anschließend mit dem Akku ODER-Verknüpft.

Man könnte also auch schreiben:

 asl $082d
 ora $082d

Wenn ihr jetzt mal in die Mnemonics schaut, werdet ihr feststellen, dass diese beiden Befehle zusammen 6Bytes und 10TZ benötigen. Wir können mit SLO also, 3Byte Speicher und 4TZ sparen, das ist schonmal nicht schlecht. Außerdem können wir Daten über Adressierungsarten shiften, die es beim ASL nicht gibt (z. B. absolut,Y).

Übersicht der Adressierungsarten:

Adressierung | OpCode | Bytes | TZ
absolut      |  $0f   |   3   |  6
absolut,X    |  $1f   |   3   |  7
absolut,Y    |  $1b   |   3   |  7
Zero-Page    |  $07   |   2   |  5
Zero-Page,X  |  $17   |   2   |  6
indirekt X   |  $03   |   2   |  8
indirekt Y   |  $13   |   2   |  8

Sollte euer Assembler diesen Befehl nicht verstehen, könnt ihr ihn z. B. durch die angabe der Bytes !byte $0f, $2d, $08 (entspricht slo $082d) trotzdem verwenden.

RLA
 rla $082d

RLA: ROL+AND
RLA absolut ($2F, 3B, 6T, NZC)
RLA kombiniert ein ROL mit einem AND. Dabei wird das über die Adressierung zufindene Byte zunächst per ROL bitweise nach links verschoben (von rechts wird das C-Flag eingeschoben) und anschließend mit dem Akku UND-Verknüpft.

Man könnte also auch schreiben:

 rol $082d
 and $082d

Übersicht der Adressierungsarten:

Adressierung | OpCode | Bytes | TZ
absolut      |  $2f   |   3   |  6
absolut,X    |  $3f   |   3   |  7
absolut,Y    |  $3b   |   3   |  7
Zero-Page    |  $27   |   2   |  5
Zero-Page,X  |  $37   |   2   |  6
indirekt X   |  $23   |   2   |  8
indirekt Y   |  $33   |   2   |  8
SRE bzw. LSE
 SRE $082d

SRE: LSR+EOR (alternatives Mnemonic: LSE)
SRE absolut ($4F, 3B, 6T, NZC)
SRE kombiniert ein LSR mit einem EOR. Dabei wird das über die Adressierung zufindene Byte zunächst per LSR bitweise nach rechts verschoben und anschließend mit dem Akku exklusiv-ODER-Verknüpft.

Man könnte also auch schreiben:

 lsr $082d
 eor $082d

Übersicht der Adressierungsarten:

Adressierung | OpCode | Bytes | TZ
absolut      |  $4f   |   3   |  6
absolut,X    |  $5f   |   3   |  7
absolut,Y    |  $5b   |   3   |  7
Zero-Page    |  $47   |   2   |  5
Zero-Page,X  |  $57   |   2   |  6
indirekt X   |  $43   |   2   |  8
indirekt Y   |  $53   |   2   |  8
RRA
 RRA $082d

RRA: ROR+ADC
RRA absolut ($6F, 3B, 6T, NZ)
RRA kombiniert ein ROR mit einem ADC. Dabei wird das über die Adressierung zufindene Byte zunächst per ROR bitweise nach rechts verschoben (das herausfallende Bit landet im C-Flag) und wird anschließend durch ADC mit dem Akku addiert (dabei wird natürlich auch das Carry-Flag vom ROR beachtet).

Man könnte also auch schreiben:

 ror $082d
 adc $082d

Da ADC nach dem ROR ausgeführt wird, ist das C-Flag also abhängig von der Addition, wir bekommen nach dem RRA also kein Carry-Flag für das mittels ROR hinausgeschobene Bit!!

Übersicht der Adressierungsarten:

Adressierung | OpCode | Bytes | TZ
absolut      |  $6f   |   3   |  6
absolut,X    |  $7f   |   3   |  7
absolut,Y    |  $7b   |   3   |  7
Zero-Page    |  $67   |   2   |  5
Zero-Page,X  |  $77   |   2   |  6
indirekt X   |  $63   |   2   |  8
indirekt Y   |  $73   |   2   |  8
SAX bzw. AXS
 SAX $082d

SAX: Store Akku AND X-Register to memory (alternatives Mnemonic: AXS)
SAX absolut ($8F, 3B, 4T, <keine>)
SAX funktioniert so: Die Inhalte von Akku und X-Register werden UND-Verknüpft, aber OHNE eines der beiden Register zu ändern! Das Ergbnis wird dann an der angegebenen Adresse abgelegt. Die Flags im Statusregister (SR) bleiben ebenfalls unverändert!

Wollte man das mit normalen Befehlen nachbilden, dann bräuchte man eine ganze Menge davon:

 php
 stx $082d
 pha
 and $082d
 sta $082d
 pla
 plp

Übersicht der Adressierungsarten:

Adressierung | OpCode | Bytes | TZ
absolut      |  $8f   |   3   |  4
Zero-Page    |  $87   |   2   |  3
Zero-Page,Y  |  $97   |   2   |  4
indirekt X   |  $83   |   2   |  6
LAX
 LAX $082D

LAX: LDA+LDX
LAX absolut ($AF, 3B, 4T, NZ)
LAX lädt das Byte, von der angegebenen Adresse, gleichzeitig in den Akku und ins X-Register.

Mit regulären Befehlen sehe das so aus:

 lda $082d
 ldx $082d

Übersicht der Adressierungsarten:

Adressierung | OpCode | Bytes | TZ
absolut      |  $af   |   3   |  4
absolut,Y    |  $bf   |   3   | 4-5
Zero-Page    |  $a7   |   2   |  3
Zero-Page,Y  |  $b7   |   2   |  4
indirekt X   |  $a3   |   2   |  6
indirekt Y   |  $b3   |   2   | 5-6

Hier wird bei zwei Adressierungsarten ein extra Taktzyklus benötigt, falls die Page-Grenze überschritten wird.

DCP bzw. DCM
 DCP $082d

DCP: DEC+CMP (alternatives Mnemonic: DCM)
DCP absolut ($CF, 3B, 4T, NZC)
DCP verringert das Byte, an der angegebenen Speicherstelle, mit DEC und vergleicht dieses dann mittels CMP mit dem Akku.

Mit regulären Befehlen sehe das so aus:

 dec $082d
 cmp $082d

Übersicht der Adressierungsarten:

Adressierung | OpCode | Bytes | TZ
absolut      |  $cf   |   3   |  6
absolut,X    |  $df   |   3   |  7
absolut,Y    |  $db   |   3   |  7
Zero-Page    |  $c7   |   2   |  5
Zero-Page,X  |  $d7   |   2   |  6
indirekt X   |  $c3   |   2   |  8
indirekt Y   |  $d3   |   2   |  8
ISC bzw. INS
 ISC $082d

ISC: INC+SBC (alternatives Mnemonic: INS)
ISC absolut ($EF, 3B, 6T, NZC)
ISC erhöht das Byte an der angegebenen Speicherstelle, mit INC und subtrahiert es dann mit SBC vom Akku.

Mit regulären Befehlen sehe das so aus:

 inc $082d
 sbc $082d

Übersicht der Adressierungsarten:

Adressierung | OpCode | Bytes | TZ
absolut      |  $ef   |   3   |  6
absolut,X    |  $ff   |   3   |  7
absolut,Y    |  $fb   |   3   |  7
Zero-Page    |  $e7   |   2   |  5
Zero-Page,X  |  $f7   |   2   |  6
indirekt X   |  $e3   |   2   |  8
indirekt Y   |  $f3   |   2   |  8
ALR
 ALR #$a5

ALR: AND+LSR
ALR unmittelbar ($4B, 2B, 2T, NZC)
ALR führt per AND eine UND-Verknüpfung mit dem angegebenen Wert und dem Akku durch. Abschließend wird per LSR der Akku bitweise nach rechts verschoben.

Mit regulären Befehlen sehe das so aus:

 and #$a5
 lsr

Hier gibt es nur die eben gezeigte Adressierungsart.

ACME kennt diesen Befehl nicht!

ARR
 ARR #$a5

ARR: AND+ROR
ARR unmittelbar ($6B, 2B, 2T, NZC)
ARR führt per AND eine UND-Verknüpfung mit dem angegebenen Wert und dem Akku durch. Abschließend wird per ROR der Akku bitweise nach rechts rotiert.

Mit regulären Befehlen sehe das so aus:

 and #$a5
 ror

Hier gibt es ebenfalls nur die eben gezeigte Adressierungsart.

XAA
 XAA #$a5

XAA: TXA+AND
XAA unmittelbar ($8B, 2B, 2T, NZ)
XAA kopiert den Inhalt des X-Register mit TAX in den Akku und führt dann eine UND-Verknüpfung mit dem angegebenen Wert und dem Akku durch.

Mit regulären Befehlen sehe das so aus:

 txa
 and #$a5

Wieder gibt es nur die eben gezeigte Adressierungsart.

ACME kennt diesen Befehl nicht!

Nochmal LAX, aber eigentlich OAL
 LAX #$a5

LAX (eigentlich OAL ORA+AND+LDX )
LAX unmittelbar ($AB, 2B, 2T, NZ)
Jetzt wird es langsam echt verrückt. 😉
Diese Version von LAX führt zuerst per ORA eine ODER-Verknüpfung mit dem Akku und dem Wert #$ee durch! Dann wird der Akku durch AND mit dem angegebenen Wert UND-Verknüpft und anschließend mittels TAX ins X-Register kopiert.

Mit regulären Befehlen sehe das so aus:

 ora #$ee
 and #$a5
 tax

Wieder gibt es nur die eben gezeigte Adressierungsart. Das C64 Studio kennt diesen Befehl, als LAX. Andere Assembler kennen OAL, was eigentlich auch besser ist, da sich das Verhalten von den anderen LAX-Befehlen unterscheidet.

ACME kennt übrigens keinen der beiden Befehle!

AXS
 AXS #$a5

AXS: AND+TAX+Subtract (oder SAX)
AXS unmittelbar ($CB, 2B, 2T, NZ)
Hier wird zuerst eine UND-Verknüfung zwischen dem Akku und dem X-Register vorgenommen. Dann wird vom Ergebnis der UND-Verknüpfung der angegebenen Wert abgezogen (ohne das Carry-Flag zu beachten!) und das Ergebnis im X-Register gespeichert. Das C-Flag kann aber durch die Subtraktion wiederum gesetzt werden, das OVerflow-Flag bleibt allerdings, ebenso wie der Akku, unverändert!

Ein Nachbau ist nur mit Hilfe einer Speicheradresse möglich, nehmen wir $fb auf der Zero-Page (AXS kommt natürlich ohne $fb aus):

 sta $fb
 txa
 and $fb
 sec
 sbc #$a5
 tax
 lda $fb

Wieder gibt es nur die eben gezeigte Adressierungsart.

ACME kennt auch diesen Befehl nicht!

SKB
 SKB

SKB: SKip next Byte (nächstes Byte überspringen)
SKB implizit ($80, 1B, 2-4T, <keine>)
Der Befehl SKB überspringt einfach das nächste Byte. Ein Nachbau würde nur einen Sprungbefehl (z. B. JMP) verwenden. Der Befehl kann auch noch mit weiteren OpCodes ausgelöst werden:
$82, $c2, $e2, $04, $14, $34, $44, $54, $64, $74, $d4, $f4
Eine genaue Angabe der Taktzyklen konnte ich leider nicht finden, nur das sie zwischen 2 und 4 liegen.

Weder das C64 Studio noch ACME kennen diesen Befehl!

SKW
 SKW

SKW: SKip next Word (nächstes Word [zwei Byte] überspringen)
SKW implizit ($0C, 1B, 4-5T, <keine>)
Der Befehl SKW überspringt ein sog. Word (das wiederum zwei Byte entspricht). Ein Nachbau könnte wie beim SKB mit einem Sprungbefehl (z. B. JMP) erfolgen oder mit dem BIT-OpCode (wobei der das Statusregister verändert!). SKW kann auch noch mit weiteren OpCodes ausgelöst werden: $1c, $3c, $5c, $7c, $dc, $fc
Intern ist SKW eine Leseoperation, nur dass das Ergebnis nirgends gespeichert wird. Beim OpCode $0c wird eine absolute Adressierung verwendet, bei den anderen wird die absolute X-Indizierte Adressierung verwendet, dort wird dann beim Überschreiten der Page-Grenze ein weiterer Taktzyklus benötigt.

Auch diesen Befehl kennen weder ACME noch das C64 Studio.

NOP
 NOP

Zum Schluß der relativ sicher verwendbaren OpCodes, bleibt noch der uns bereits bekannte NOP-Befehl. Dieser wird nicht nur beim offiziellen OpCode $ea ausgeführt, sondern auch bei ($1a, $3a, $5a, $7a, $da, $fa).

Jetzt wird es noch illegaler 😉

Die nun folgenden OpCodes sind im Buch „The Complete Commodore Inner Space Anthology“ nicht mehr beschrieben. Ich habe sie nur im Netz gefunden, allerdings ist ihr verhalten teilweise nicht vorhersagbar. Da VICE diese Befehle kennt und verarbeitet, führe ich sie der Vollständigkeit halber auf.
Die kommen Befehle werden jetzt immer verrückter und problematischer, ein sinnvoller Einsatz ist daher äußerst fragwürdig!

HLT
 HLT

HLT: HaLT (Absturz verursachen)
HLT implizit ($02, 1B, ?T, <keine>)
Tja, was soll man dazu sagen?
Triff die CPU auf einen dieser OpCodes $02, $12, $22, $32, $42, $52, $62, $72, $92, $b2, $d2, $f2, dann „hängt“ sie sich auf! Nur ein Reset bzw. Neustart hilft dann weiter. Taktzyklen sind hier nicht auffindbar und wären auch vollkommen irrelevant, der Rechner steht dann eh!

Weder ACME, noch das C64 Studio kennen diesen Befehl.

TAS
 TAS $082d,y

TAS: TXS+AND+STA
TAS absolut Y-indiziert ($9B, 3B, 5T, <keine>)
Zunächst werden der Akku und das X-Register per UND-Verknüpft, aber ohne das sich eines der Register ändert! Das Ergebnis wird in den Stackpointer (SP / nicht auf den Stack!!!) geschrieben. Dann wird das Ergebnis mit dem (Wert des MSB)+1 der angegebenen Adresse UND-Verknüpft und im Speicher an der angegebenen Adresse+Y-Register abgelegt. Wenn ihr das ausprobieren wollt, achtet auf den Stackpointer. Da der sehr wahrscheinlich geändert wurde (das sollte schon ein ungeheurer Zufall sein, wenn die erste UND-Verknüpfung den selben Wert wie der aktuelle SP ergibt) solltet ihr ihn mit TSX / TXS in einer Speicherstelle sichern und wiederherstellen. Die Flags bleiben dabei unverändert.

Auch das läßt sich nur unter Zuhilfenahme weiterer Speicherstellen (wir nehmen $fb & $fc auf der Zero-Page) nachbauen:

Wir gehen vom Befehl TAS $082d,y aus.

 stx $fb     ;X in die Zero-Page, da es kein direktes AND für X und Akku gibt
 pha         ;Akku merken
 php         ;SR auf den Stack
 pla         ;SR in den Akku
 sta $fc     ;SR auf Zero-Page sichern
 pla         ;Akku wiederherstellen
 pha         ;und direkt wieder 'retten'
 and $fb     ;Akku mit X (jetzt in $FB) UND-Verknüpfen
 sta $fb     ;Ergebnis für später in $FB merken
 and #$09    ;UND-Verknüpung mit dem MSB ($08)+1 = $09
 sta $082d,y ;Ergebnis aus dem Akku Speichern
 txa         ;X im Akku merken
 ldx $fb     ;Ergebnis der 1. UND-Verknüpfung nach X holen
 sta $fb     ;Akku (gemerktes X) jetzt an $FB merken
 pla         ;original Akku wiederholen (muss VOR dem TXS geschehen!!)
 txs         ;X in den SP kopieren TAX
 ldx $fb     ;auf der Zero-Page gemerktes X zurückholen
 sta $fb     ;Akku auf dem Stack merken
 lda $fc     ;SR in den Akku
 pha         ;SR vom Akku auf den Stack
 lda $fb     ;Akku wiederherstellen
 plp         ;SR wieder auf Ausgangswert setzen

Soviel Aufwand für nichts, hat jemand einen sinnvollen Einsatz hierfür???
Weitere Adressierungsarten gibt es übrigens nicht.

SAY
 SAY $082d,x

SAY: Store value AND Y-Register
SAY absolut X-indiziert ($9C, 3B, 5T, <keine>)
Es wird das Y-Register mit dem Wert des MSB+1 UND-Verknüpft und anschließend an der angegebenen Adresse gespeichert. Die Flags bleiben dabei unverändert.

Nachbauen läßt sich das ganz einfach:

 php
 pha
 tya
 and #$09    ;MSB von SAY $082D,Y = $08 zzgl. 1 = $09
 sta $082d,x
 pla
 plp

Auch hier gibt es keine anderen Adressierungsarten.

Weder ACME, noch das C64 Studio kennen diesen Befehl.

XAS
 XAS $082d,y

XAS: X-Reg. AND value Stored to memory
XAS absolut Y-indiziert ($9E, 3B, 5T, <keine>)
Es wird das X-Register mit dem Wert des MSB+1 UND-Verknüpft und anschließend an der angegebenen Adresse gespeichert. Die Flags bleiben dabei unverändert.

Nachbauen läßt sich das ganz einfach:

 php
 pha
 txa
 and #$09     ;MSB von XAS $082D,Y = $08 zzgl. 1 = $09
 sta $082d,y
 pla
 plp

Auch hier gibt es keine anderen Adressierungsarten.

Weder ACME, noch das C64 Studio kennen diesen Befehl.

AXA
 AXA $082d,y

AXA: Akku and X-Reg. STA
AXA absolut Y-indiziert ($9F, 3B, 5T, <keine>)
Es wird der Akku mit dem X-Register und anschließend mit dem Wert des MSB+1 UND-Verknüpft. Anschließend wird das Ergebnis an der angegebenen Adresse gespeichert. Die Flags bleiben dabei unverändert.

Zum Nachbauen benötigen wir wieder eine Speicherstelle, die der Befehl natürlich nicht verwendet, nehmen wir wieder $fb auf der Zero-Page:

 php
 stx $fb
 pha
 and $fb
 and #$09
 sta $082d,y
 pla
 ldx $fb
 plp

Übersicht der Adressierungsarten:

Adressierung | OpCode | Bytes | TZ
indirekt Y   |  $93   |   2   |  6

Weder ACME, noch das C64 Studio kennen diesen Befehl.

ANC
 ANC #$4d

ANC: Akku AND value influence Carry
ANC unmittelbar ($2B, 2B, 2T, NZC)
Der Akku wird mit dem angegebenen Wert UND-Verknüpft. Das Ergebnis steht dann auch wieder im Akku. Er sieht also zunächst wie ein normaler AND-Befehl aus, aber hier wird das N-Flag ins Carry-Flag kopiert.

Der OpCode $0b führt zum selben Befehl, wie der eben erwähnte $2b .

Ein Nachbau könnte so aussehen:

 and #$4d
 bmi setCarry
 clc
 skb
setCarry
 sec
LAS
 LAS $082d,y

LAS: Hierzu fällt mir nur: Lade Alles mit Schrott ein 😉
LAS absolut Y-indiziert ($BB, 3B, 2T, NZ)
Der Befehl führt eine UND-Verknüpfung mit dem Byte das an der angegebenen Speicherstelle zufinden ist und dem Stackpointer (SP) durch. Das Ergebnis wird dann im Akku, X-Register und SP abgelegt.

Zum letzten Mal ein Nachbau:

 tsx
 txa
 and $082d,y
 tax
 txs

Zwei letzte OpCodes, für bekannte Befehle soll es noch geben, aber auch die sind nicht abgesichert:

$89 soll ebenfalls ein NOP ausführen.

$eb soll einem einem SBC #value entsprechen.


Wer ein Wenig sucht, findet seitenweise Diskussionen über diese Befehle. Wie bereits erwähnt, gibt es teilweise ein unterschiedliches Verhalten auf verschiedenen Rechnern und teilweise bei verschiedenen Ausgangssituationen auf dem selben Computer.
Daher nochmal die Warnung mit diesen Befehlen sparsam umzugehen!
Nichts ist frustrierender als stundenlang einen Fehler zu suchen und dann festzustellen, dass der illigale OpCode sich diesmal anders verhält nur weil der Bildschirmspeicher andere Daten enthält.


So, jetzt haben wir aber wirklich alle Befehle einmal gesehen. Als nächstes gibt es noch einen ‚Abschluß‘-Beitrag und dann sind wir mit dem Assembler-Grundlagen-Tutorial durch. Danach geht es mit dem Programmieren endlich richtig los.


Schrott!!Naja...Geht so...Ganz gut...SUPER! (13 Bewertungen | Ø 4,77 von 5 | 95,38%)

Loading...


ZurückWeiter

3 Gedanken zu „Alles illegal!“

  1. Meine aktive Zeit ist zwar Jahrzehnte her, aber ich meine mich dran erinnern zu können dass es auch illegale Opcodes gab für Double NOP / triple NOP.

    Und zum Thema der Sinnvollen einsetzbarkeit von illegalen Opcodes, so wurden so einige davon öfter benutzt um Zyklen zu sparen. Vieles wurde für visuelle Darstellung und für Rasterinterrupts benutzt. Da kam es teilweise auf jeden Zyklus an. Hat das Timing nicht gestimmt, war die Rasterzeile nicht am Ende der Zeile.

    Bin nur gerade nicht mehr sicher, ob Zyklus der richtige Name noch dafür war. Schon zu lange her.

    Aber ein NOP hatte 2 und ein Double NOP 3 als Bsp.

  2. Für mich macht der HLT Befehl dahingehend Sinn, das man damit eine Codeanipulationssicherung / Kopierschutz bauen könnte (Reines Gedankenspiel ohne jetzt eine konkrete Umsetzung im Hinterkopf zu haben)
    Bei Fehlverhalten würde der Rechner mittels HLT eingefroren. Somit würde kein Warmstart oder Softwarereset helfen also der Speicher nicht reproduzierbar sein. Oder täusche ich mich ?

    1. Klappt nicht da der Reset weiterhin möglich ist, wenn man aber die CMD80 Kennung auf eine $02 setzt dann nützt einem der Reset auch nix mehr. und man könnte so nur noch mit einem Kaltstart den C64 nutzen

Schreibe einen Kommentar

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

Protected by WP Anti Spam