====== 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