====== 8080 CPU Simulator – Befehlssatz ======
Diese Seite beschreibt alle vom [[simulator:overview|8080 CPU Simulator]] unterstützten Befehle des **Intel 8080-Mikroprozessors**.
Alle Instruktionen sind originalgetreu implementiert und können direkt im [[https://www.seolizer.de/asm/|Online-Simulator]] getestet werden.
===== Register-Konvention =====
* 8-Bit-Register: **A, B, C, D, E, H, L**
* 16-Bit-Registerpaare: **BC, DE, HL, SP**
* **M** bezeichnet das Speicherbyte an der Adresse, die im Registerpaar HL steht.
===== Legende =====
^ Spalte ^ Bedeutung ^
| **Mnemonic** | Assembler-Kurzform |
| **Operanden** | Register, Adresse oder Konstante |
| **Beschreibung** | Wirkung der Instruktion |
| **Flags** | Betroffene Statusflags (S,Z,AC,P,CY) |
| **Anmerkung** | Besonderheiten oder Hinweise |
----
===== Datentransfer-Befehle – Kurzreferenz =====
Diese Befehle verschieben Daten zwischen Registern, Speicherzellen und Konstanten.
Sie verändern keine Flags und dienen ausschließlich dem **Transport von Informationen**.
^ Befehl ^ Operanden ^ Kurzbeschreibung ^
| **MOV r1,r2** | Register, Register | Kopiert Inhalt von r2 nach r1 (auch M für Speicher via HL möglich). |
| **MVI r,data** | Register, 8-Bit-Wert | Lädt eine Konstante direkt in ein Register oder in [HL]. |
| **LXI rp,data16** | Registerpaar, 16-Bit-Wert | Lädt ein Registerpaar (BC, DE, HL, SP) mit einem 16-Bit-Wert. |
| **LDA addr** | 16-Bit-Adresse | Lädt A mit dem Wert aus der angegebenen Speicheradresse. |
| **STA addr** | 16-Bit-Adresse | Speichert den Wert von A in der angegebenen Speicheradresse. |
| **LHLD addr** | 16-Bit-Adresse | Lädt H und L aus zwei aufeinanderfolgenden Speicherzellen. |
| **SHLD addr** | 16-Bit-Adresse | Speichert H und L in zwei aufeinanderfolgenden Speicherzellen. |
| **LDAX rp** | BC / DE | Lädt A mit dem Byte, auf das BC oder DE zeigt. |
| **STAX rp** | BC / DE | Speichert A an die Adresse, auf die BC oder DE zeigt. |
| **XCHG** | – | Tauscht Inhalte von DE ↔ HL. |
| **XTHL** | – | Tauscht HL mit dem obersten Stack-Eintrag ([SP]/[SP+1]). |
| **SPHL** | – | Kopiert HL in SP → neuer Stack-Pointer. |
----
**Hinweise:**
* Alle Datentransfer-Instruktionen lassen die Flags unverändert.
* Indirekte Speicherzugriffe erfolgen stets über das Registerpaar **HL** (als **M**) oder über **BC/DE** (bei LDAX/STAX).
* Diese Befehle bilden die Grundlage für Speicheroperationen, Adressierung und Parameterübergaben in Unterprogrammen.
===== Erklärung der Datentransfer-Befehle =====
Die Datentransferbefehle dienen zum **Kopieren, Laden und Speichern von Daten** zwischen Registern, Speicherzellen und Konstanten.
Sie verändern keine Flags (Z, S, CY etc.) und sind damit reine „Bewegungsbefehle“.
In der Praxis werden sie ständig genutzt, um Werte zwischen CPU-Registern und Speicher zu übertragen.
----
==== MOV r1, r2 ====
Kopiert den Inhalt des Registers **r2** in **r1**.
Dieser Befehl ist der einfachste Weg, Daten zwischen zwei Registern zu verschieben.
Auch das Speicherbyte an der Adresse von **HL** kann mit **M** angesprochen werden.
**Beispiel:**
MOV A,B ; A ← B
MOV M,A ; [HL] ← A
MOV C,M ; C ← [HL]
Flags werden nicht verändert.
**Tipp:** MOV-Befehle sind ideal für Zwischenspeicherungen oder Registertausch ohne Rechenoperation.
==== MVI r, data ====
Lädt einen sofortigen (immediate) 8-Bit-Wert direkt in ein Register.
Damit lassen sich Register initialisieren, z. B. mit Zahlen oder ASCII-Zeichen.
**Beispiel:**
MVI A,42h ; Lade 0x42 in A
MVI M,'H' ; Schreibe ASCII-'H' in [HL]
Wird M als Ziel verwendet, schreibt der Befehl den Wert in die Speicherzelle, auf die HL zeigt.
==== LXI rp, data16 ====
Lädt einen 16-Bit-Wert (z. B. eine Speicheradresse) in ein Registerpaar (BC, DE, HL oder SP).
Wird häufig verwendet, um Zeiger oder Stackpositionen zu setzen.
**Beispiel:**
LXI H,2000h ; HL zeigt auf Adresse 2000h
LXI SP,FFFFh ; Stackpointer auf oberes Ende
Da der Intel 8080 keine eigenen Ladebefehle für 16-Bit-Zahlen in Einzelregister kennt,
ist LXI essenziell für Adressierung und Stackverwaltung.
==== LDA addr ====
Lädt den Akkumulator A mit dem Wert aus der direkten Speicheradresse.
Das ist eine absolute Adressierung – nicht über HL, sondern direkt über den im Befehl angegebenen Wert.
**Beispiel:**
LDA 2050h ; A ← [2050h]
Anwendung: Lesen einer Speicherzelle, z. B. einer Variablen oder Eingabedaten.
==== STA addr ====
Speichert den Inhalt des Akkumulators A in die angegebene Speicheradresse.
Dies ist das Gegenstück zu LDA.
**Beispiel:**
STA 2100h ; [2100h] ← A
Anwendung: Schreiben eines Ergebnisses in den Speicher.
==== LHLD addr ====
Lädt das Registerpaar HL mit zwei aufeinanderfolgenden Bytes aus dem Speicher.
Der Wert an [addr] wird nach L, und der an [addr+1] nach H geladen.
**Beispiel:**
LHLD 3000h ; L ← [3000h], H ← [3001h]
Wird häufig für den Import von 16-Bit-Zahlen oder Zeigern verwendet.
==== SHLD addr ====
Speichert den Inhalt des Registerpaars HL in zwei aufeinanderfolgende Speicherzellen.
Das erste Byte (L) wird nach [addr], das zweite (H) nach [addr+1] geschrieben.
**Beispiel:**
SHLD 3000h ; [3000h] ← L, [3001h] ← H
Anwendung: Zwischenspeicherung eines 16-Bit-Ergebnisses im Speicher.
==== LDAX rp ====
Lädt den Akkumulator A mit dem Byte aus dem Speicher, auf das das Registerpaar BC oder DE zeigt.
Diese indirekte Adressierung ist besonders praktisch bei Datenkopien oder Zeichenketten.
**Beispiel:**
LDAX D ; A ← [DE]
**Wichtig:** Nur BC oder DE sind erlaubt – HL darf hier nicht verwendet werden.
==== STAX rp ====
Speichert den Akkumulator A an die Speicheradresse, die in BC oder DE steht.
Gegenstück zu LDAX.
**Beispiel:**
STAX B ; [BC] ← A
Wird häufig in Schleifen verwendet, um Bytefolgen im Speicher zu füllen.
==== XCHG ====
Tauscht den Inhalt der Registerpaare DE und HL.
Praktisch, wenn man zwei Zeiger oder Adressregister kurzzeitig vertauschen muss.
**Beispiel:**
XCHG ; DE ↔ HL
Flags bleiben unverändert.
==== XTHL ====
Tauscht das Registerpaar HL mit dem obersten Wert auf dem Stack (Adresse durch SP definiert).
Dadurch kann man schnell auf Zwischenergebnisse zugreifen oder temporäre Werte sichern.
**Beispiel:**
XTHL ; H,L ↔ [SP+1],[SP]
Anwendung: Lokale Variablen in Unterprogrammen oder Stackmanipulationen.
==== SPHL ====
Kopiert das Registerpaar HL in den Stackpointer SP.
Wird verwendet, um den Stack auf eine bestimmte Speicherposition umzuleiten.
**Beispiel:**
SPHL ; SP ← HL
**Tipp:** Besonders nützlich in Unterprogrammen, die eigene Stackbereiche nutzen sollen.
Insgesamt bilden diese Befehle die „Transportrouten“ innerhalb der CPU:
Sie verschieben Daten zwischen Registern, Speicher und Adressen, ohne sie zu verändern –
und bilden damit die Grundlage jeder Assemblerprogrammierung.
----
===== Arithmetische Befehle =====
^ Mnemonic ^ Operanden ^ Beschreibung ^ Flags ^ Anmerkung ^
| ADD r | Register | A ← A + r | S,Z,AC,P,CY | – |
| ADI data | 8-Bit-Wert | A ← A + data | S,Z,AC,P,CY | – |
| ADC r | Register | A ← A + r + CY | S,Z,AC,P,CY | Mit Carry |
| ACI data | 8-Bit-Wert | A ← A + data + CY | S,Z,AC,P,CY | – |
| SUB r | Register | A ← A – r | S,Z,AC,P,CY | – |
| SUI data | 8-Bit-Wert | A ← A – data | S,Z,AC,P,CY | – |
| SBB r | Register | A ← A – r – CY | S,Z,AC,P,CY | – |
| SBI data | 8-Bit-Wert | A ← A – data – CY | S,Z,AC,P,CY | – |
| INR r | Register | r ← r + 1 | S,Z,AC,P | Carry bleibt |
| DCR r | Register | r ← r – 1 | S,Z,AC,P | Carry bleibt |
| INX rp | Registerpaar | rp ← rp + 1 | – | 16-Bit-Inkrement |
| DCX rp | Registerpaar | rp ← rp – 1 | – | 16-Bit-Dekrement |
| DAD rp | Registerpaar | HL ← HL + rp | CY | 16-Bit-Addition |
| DAA | – | Dezimal-Anpassung nach ADD | S,Z,AC,P,CY | BCD-Korrektur |
----
===== Erklärung der Arithmetischen Befehle =====
Die arithmetischen Befehle führen **Addition, Subtraktion und Inkrement-/Dekrement-Operationen** auf Registern oder Speicherwerten aus.
Das Ergebnis wird normalerweise im **Akkumulator (A)** gespeichert, und **mehrere Status-Flags** (S, Z, AC, P, CY) werden entsprechend gesetzt.
Diese Flags ermöglichen anschließende Vergleiche und bedingte Sprünge.
----
==== ADD r ====
Addiert den Wert des angegebenen Registers (oder von [HL]) zum Akkumulator **A**.
Ergebnis wird in **A** gespeichert, Flags werden angepasst.
**Beispiel:**
MVI A,05h
MVI B,03h
ADD B ; A = 08h, CY=0, Z=0
**Hinweis:**
Der Befehl verändert A und alle relevanten Flags (S, Z, AC, P, CY).
==== ADI data ====
Addiert einen sofortigen 8-Bit-Wert zu A.
Wird häufig genutzt, um konstante Werte zu addieren.
**Beispiel:**
MVI A,10h
ADI 05h ; A = 15h
==== ADC r / ACI data ====
Wie ADD bzw. ADI, jedoch wird zusätzlich das Carry-Flag (CY) in die Rechnung einbezogen.
Das ist wichtig bei mehrbyteweisen Additionen, etwa für 16-Bit-Werte.
**Beispiel (Addition zweier 16-Bit-Zahlen):**
LXI H,2000h
LXI D,2100h
MOV A,M
ADD E
MOV M,A
INX H
INX D
MOV A,M
ADC E ; <---- Übertrag
MOV M,A
Hier sorgt ADC dafür, dass der Übertrag aus dem ersten Byte übernommen wird.
==== SUB r / SUI data ====
Subtrahiert den Wert des Registers (oder eine Konstante) von A.
Ergebnis → A, Flags entsprechend gesetzt.
**Beispiel:**
MVI A,08h
MVI B,03h
SUB B ; A = 05h, CY=0
SUI data funktioniert analog, nur mit einem sofortigen Wert:
MVI A,10h
SUI 01h ; A = 0Fh
==== SBB r / SBI data ====
Wie SUB bzw. SUI, aber unter Berücksichtigung des Carry-Flags (CY).
Wird vor allem bei mehrbyteweisen Subtraktionen benötigt.
**Beispiel:**
MVI A,00h
SUI 01h ; A = FFh, CY=1
SBI 00h ; A = FEh, CY=1 (mit Borrow)
==== INR r / DCR r ====
Erhöht oder verringert ein Register (oder [HL]) um 1.
Carry-Flag bleibt unverändert, alle anderen relevanten Flags werden aktualisiert.
**Beispiel:**
MVI B,09h
INR B ; B = 0Ah
DCR B ; B = 09h
Typisch in Schleifen:
LOOP: DCR C
JNZ LOOP
==== INX rp / DCX rp ====
Erhöht oder verringert ein Registerpaar (BC, DE, HL, SP) um 1.
Diese Operation wirkt 16-Bit-weise, Flags bleiben unverändert.
**Beispiel:**
LXI H,1FFFh
INX H ; HL = 2000h
DCX H ; HL = 1FFFh
==== DAD rp ====
Addiert den Inhalt eines Registerpaares zum Registerpaar HL.
Das Ergebnis ersetzt HL, nur das Carry-Flag (CY) wird angepasst.
**Beispiel:**
LXI H,1000h
LXI D,2000h
DAD D ; HL = 3000h
**Anwendung:** Zeigerarithmetik oder 16-Bit-Additionen.
==== DAA (Decimal Adjust Accumulator) ====
Korrigiert das Ergebnis einer vorherigen Addition, wenn mit BCD-Zahlen (dezimal kodiert) gerechnet wird.
Falls der niederwertige Nibble (Bit 0–3) > 9 oder AC=1 ist, wird 6 addiert.
Falls der höherwertige Nibble > 9 oder CY=1 ist, werden weitere 6 auf Bit 4–7 addiert.
**Beispiel:**
MVI A,09h
ADI 09h ; A = 12h (dezimal 18)
DAA ; A = 18h (korrektes BCD-Ergebnis)
Arithmetische Befehle sind die Grundlage aller Rechenoperationen.
Sie verändern den Zustand der CPU-Flags und ermöglichen dadurch bedingte Programmsteuerung,
z. B. durch JZ, JC, JP oder JM nach einer Berechnung.
----
===== Logische Befehle =====
^ Mnemonic ^ Operanden ^ Beschreibung ^ Flags ^ Anmerkung ^
| ANA r | Register | A ← A AND r | S,Z,AC,P,CY=0 | Logisches UND |
| ANI data | 8-Bit-Wert | A ← A AND data | S,Z,AC,P,CY=0 | – |
| ORA r | Register | A ← A OR r | S,Z,AC,P,CY=0 | – |
| ORI data | 8-Bit-Wert | A ← A OR data | S,Z,AC,P,CY=0 | – |
| XRA r | Register | A ← A XOR r | S,Z,P,CY=0,AC=0 | – |
| XRI data | 8-Bit-Wert | A ← A XOR data | S,Z,P,CY=0,AC=0 | – |
| CMP r | Register | A – r (nur Flags) | S,Z,AC,P,CY | Kein Ergebnis gespeichert |
| CPI data | 8-Bit-Wert | A – data (nur Flags) | S,Z,AC,P,CY | Vergleichsbefehl |
| CMA | – | A ← NOT A | – | Bitweise Negation |
| CMC | – | CY ← NOT CY | CY | Carry invertieren |
| STC | – | CY ← 1 | CY | Carry setzen |
----
===== Rotations- und Spezialbefehle =====
^ Mnemonic ^ Operanden ^ Beschreibung ^ Flags ^ Anmerkung ^
| RLC | – | A ← (links rot durch Carry) | CY | Bit 7 → Bit 0 → CY |
| RRC | – | A ← (rechts rot durch Carry) | CY | Bit 0 → Bit 7 → CY |
| RAL | – | Linksrotation durch Carry einbeziehen | CY | CY ↔ Bit 0 |
| RAR | – | Rechtsrotation durch Carry einbeziehen | CY | CY ↔ Bit 7 |
----
===== Sprungbefehle =====
^ Mnemonic ^ Operanden ^ Beschreibung ^ Flags ^ Anmerkung ^
| JMP addr | 16-Bit-Adresse | PC ← addr | – | Unbedingter Sprung |
| JZ addr | 16-Bit-Adresse | Wenn Z=1 → PC ← addr | – | Sprung bei Zero |
| JNZ addr | 16-Bit-Adresse | Wenn Z=0 → PC ← addr | – | Sprung bei nicht Zero |
| JC addr | 16-Bit-Adresse | Wenn CY=1 → PC ← addr | – | Sprung bei Carry |
| JNC addr | 16-Bit-Adresse | Wenn CY=0 → PC ← addr | – | Sprung bei kein Carry |
| JP addr | 16-Bit-Adresse | Wenn S=0 → PC ← addr | – | Sprung bei positiv |
| JM addr | 16-Bit-Adresse | Wenn S=1 → PC ← addr | – | Sprung bei negativ |
| JPE addr | 16-Bit-Adresse | Wenn P=1 → PC ← addr | – | Sprung bei gerader Parität |
| JPO addr | 16-Bit-Adresse | Wenn P=0 → PC ← addr | – | Sprung bei ungerader Parität |
| PCHL | – | PC ← HL | – | Indirekter Sprung |
----
===== Unterprogramme (CALL/RET) =====
^ Mnemonic ^ Operanden ^ Beschreibung ^ Flags ^ Anmerkung ^
| CALL addr | 16-Bit-Adresse | Rücksprungadresse → Stack, PC ← addr | – | Unterprogrammaufruf |
| RET | – | PC ← [Stack] | – | Rückkehr aus Unterprogramm |
| CNZ/CZ | addr | CALL wenn Z=0/1 | – | Bedingte Aufrufe |
| CNC/CC | addr | CALL wenn CY=0/1 | – | – |
| CPO/CPE | addr | CALL wenn P=0/1 | – | – |
| CP/CM | addr | CALL wenn S=0/1 | – | – |
| RNZ/RZ | – | RET wenn Z=0/1 | – | Bedingte Rückkehr |
| RNC/RC | – | RET wenn CY=0/1 | – | – |
| RPO/RPE | – | RET wenn P=0/1 | – | – |
| RP/RM | – | RET wenn S=0/1 | – | – |
----
===== Stack & Interrupts =====
^ Mnemonic ^ Operanden ^ Beschreibung ^ Flags ^ Anmerkung ^
| PUSH rp | BC/DE/HL/PSW | Stack ← rp | – | PSW = A+Flags |
| POP rp | BC/DE/HL/PSW | rp ← Stack | Flags | PSW restauriert |
| EI | – | Interrupts aktivieren | – | – |
| DI | – | Interrupts deaktivieren | – | – |
| NOP | – | Keine Operation | – | Wird ignoriert |
| HLT | – | Stoppt CPU | – | Simulation pausiert |
----
===== Beispiel =====
```asm
MVI A,09h
MVI B,03h
ADD B
STA E000h ; schreibt Ergebnis in VRAM
HLT