| 1.2 Bedienung des µRechners |  | 1.4 Anleitung zur Lösung der Übungsaufgaben |

1.3/1

## 1.3 Der Mikroprozessor 6809

### 1.3.1 Die Architektur

Der Prozessor 6809 ist ein 8-bit-Mikroprozessor aus der 68xx-Bausteinreihe von Motorola. Er ist gegenüber seinen "Vorgängern" 6800 und 6802 wesentlich verbessert und verfügt intern zum Teil über eine 16-bit-Struktur, denn die meisten Register sind 16 bit breit. Sie ermöglichen somit 16-bit-Operationen. Diese werden jedoch in mehreren Schritten durch eine 8-bit-ALU ausgeführt. Die beiden 8-bit-Akkumulatoren (A und B) lassen sich für einige Operationen zu einem 16-bit-Akkumulator (D) zusammenschalten (A: H-Byte, B: L-Byte). Bild 1.3-1 zeigt die interne Organisation des 6809. Der 6809 1) ist in einem DIL-Gehäuse (dual inline) mit 40 Anschlüssen untergebracht.

Bild 1.3-1: | Interne Organisation des 6809 |

1.3/2

### 1.3.2 Steuer- und Statussignale

Die Steuer- und Statussignale des 6809 lassen sich in vier Gruppen einteilen 2):

- Taktsignale
- Systembus-Zugriffssteuersignale
- Speicher-Steuersignale
- Unterbrechungssignale

1. Taktsignale

Der 6809 verfügt über einen internen Taktgenerator, so daß an den Anschlüssen XTAL und EXTAL extern nur ein Quarz angeschlossen wird. Je nach Ausführung kann der 6809 mit einem 4, 6 oder 8 MHz-Quarz betrieben werden 3). Die für den Maschinenzyklus maßgebende interne Taktfrequenz beträgt ein Viertel der Quarzfrequenz, so daß Zykluszeiten zwischen 500 ns und 1 s erreicht werden. Aus diesem Taktsignal werden intern zwei Takte abgeleitet (vgl. die folgende Skizze in Bild 1.3-2 für eine Quarzfrequenz von 8 MHz):

- Das E-Signal: Mit der fallenden Flanke des Signals E (Enable, freigeben) werden die Daten vom Prozessor bzw. von den Speicher- und Peripheriebausteinen übernommen. Die Adreß- und Steuerleitungen werden in den ersten 200 ns stabil.
- Das Q-Signal: Die steigende Flanke des Taktes Q zeigt an, daß alle Ausgangssignale des Prozessors gültig sind.

Bild 1.3-2: | Die Taktsignale des 6809 |

1.3/3

2. Systembus-Zugriffssteuersignale

Die Steuersignale DMA/BREQ, BS und BA werden verwendet, um den Prozessor unter bestimmten Voraussetzungen vom Bussystem zu trennen und so einer anderen Rechnerkomponente den Zugriff zum Systembus zu gewähren, z.B. für den DMA-Betrieb 4) (Direct Memory Access). Wird der CPU über die #DMA/BREQ-Leitung eine Busanforderung gemeldet, gibt diese nach Beendigung des gerade ausgeführten Befehls den Daten- und Adreßbus frei, d.h. sie schaltet ihre Adreß- und Datenbustreiber in den hochohmigen Zustand (Tristate, "high impedance"). Der 6809 kann den Bus an DMA-Komponenten jeweils nur für die Dauer von 15 Taktzyklen abgeben, da er ihn danach für die Dauer von mindestens einem Taktzyklus für das Auffrischen 5) des Inhalts der internen Register (Refresh) benötigt.

Auf den Leitungen BA und BS wird der monentane Zustand angezeigt und zwar:

BA | BS | Funktion
--- | --- | ---
0 | 0 | Normaler Busbetrieb
0 | 1 | Unterbrechung oder Rücksetzen (RESET)
1 | 0 | SYNC-Quittung
1 | 1 | Bustreiber hochohmig

3. Speicher-Steuersignale

MRDY und R/#W sind die beiden Signale, die für den Speicherverkehr benötigt werden. Das MRDY-Signal 6) dient Ein-/Ausgabe-Komponenten niedriger Geschwindigkeit dazu, sich mit dem 6809 zu synchronisieren. Eine logische "0" signalisiert der CPU, daß die betreffende Einheit noch nicht bereit ist. Der 6809 wartet so lange, bis das Signal gesetzt wird. Das MRDY-Signal darf nur für maximal 10 Taktzyklen logisch "0" sein (bis zu 10 µs). Im Gegensatz zu anderen Mikroprozessoren (z.B. den Intel-Prozessoren 80x80) kennt der 6809 kein Steuersignal (Memory/Input-Output - M/IO) für den Zugriff auf Peripheriebausteine. Die Register dieser Bausteine werden wie Speicherzellen adressiert.

4. Unterbrechungssignale

Dies sind die drei Hardware-Interruptsignale #NMI, #IRQ, #FIRQ sowie die Signale #HALT, #RESET 7).

- Durch #RESET wird der Prozessor in den Anfangszustand zurückgesetzt: Der Programmzähler PC wird mit der Startadresse, das Direct Page Register DP mit $00 und das I- und F-Flag des Statusregisters CC mit "1" geladen, die übrigen Flags sind undefiniert. Auch die anderen Register (Akkumulatoren A,B, Indexregister X,Y, Stackregister U,S) sind nach einem RESET in einem nicht vorhersehbaren Anfangszustand. Der #IRQ bzw. der #FIRQ sind gesperrt. (Alle Register werden im nächsten Unterabschnitt ausführlicher beschrieben.)

  1.3/4

  In den meisten Anwendungen wird das #RESET-Signal gleichzeitig den Peripheriebausteinen zugeführt, damit diese ebenfalls in einen Grundzustand versetzt werden. Im Gegensatz zu den anderen Unterbrechungszuständen "Interrupt" und "Halt" wird der laufende Befehl nicht zu Ende geführt, sondern abgebrochen.

- Das #HALT-Signal unterbricht die Arbeit des Prozessors. Der gerade begonnene Befehl wird noch ausgeführt. Danach wartet der Prozessor, ohne seine Daten zu verlieren. Die Signale BA und BS sind logisch "1". Sobald das #HALT-Signal zurückgesetzt wird, arbeitet der Prozessor weiter.

Die Hardware-Interrupts sind der nicht maskierbare Interrupt (NMI), der schnelle maskierbare Interrupt (FIRQ) und der maskierbare Interrupt (IRQ). Sie werden durch Signale an den gleichnamigen Eingängen aktiviert.

- Signal #NMI (Non Maskable Interrupt)
  Liegt keine Busanforderung bzw. kein Signal am #DMA/BREQ-Eingang vor, so kann der NMI unverzüglich abgearbeitet werden. Im anderen Fall muß erst die Freigabe des Busses abgewartet werden. Es werden automatisch der Programmzähler PC und alle Register (Ausnahme: Stackregister U,S) auf den Systemstack geschrieben. Im Statusregister CC werden die Flags E, F und I gesetzt.
- Signal #IRQ (Maskable Interrupt)
  Der Interrupt IRQ rettet alle Register, außer dem Stackregister S, auf dem Stack. Dieser Vorgang entspricht dem bei der nicht maskierbaren Unterbrechung. Das E-Flag im Statusregister wird gesetzt. Ferner wird das I-Flag gesetzt, um weitere Unter-brechungen zu verhindern.
- Signal #FIRQ (Fast Maskable Interrupt)
  Die schnelle Unterbrechungsanforderung entspricht im wesentlichen dem IRQ. Es werden aber nur die Inhalte des Programmzählers PC und des Statusregisters CC im Stack gespeichert. Der FIRQ kann maskiert werden durch Manipulation des F-Flags im Statusregister. Um weitere Unterbrechungen zu verhindern, werden sowohl das F- wie auch das I-Flag automatisch gesetzt.

Im Vorgriff auf den nächsten Abschnitt sei hier schon einmal gesagt, daß der 6809 zusätzlich zu den Hardware-Interrupts über drei Software-Interrupts verfügt. Diese werden durch die Befehle SWI1, SWI2 und SWI3 aufgerufen und können als spezi-elle Unterprogramme angesehen werden 8). Wenn eine Software-Interruptanforderung vorliegt, werden ebenfalls alle Registerinhalte im Systemstack gerettet. SWI2 und SWI3 haben die geringste Priorität von allen Unterbrechungsanforderungen, da sie keinerlei Interrupts sperren, es wird nur das E-Flag gesetzt. Der SWI1 hingegen setzt das E-, F- und I-Flag und sperrt daher den FIRQ und den IRQ.

1.3/5

Die Startadressen (Interruptvektoren) für die Behandlungsroutinen der verschiedenen Unterbrechungen sind unter den höchsten Adressen im (Festwert-) Speicher des Praktikumsrechners abgelegt. Die folgende Tabelle 1.3-1 zeigt die Lage der Interruptvektoren.

Tabelle 1.3-1: Speicheradressen der Interruptvektoren

Adresse H-Byte L-Byte | Interrupt Vektor | Ausnahmesituation | Bemerkung
--- | --- | --- | ---
FFFE FFFF |  | #RESET | Rücksetzen
FFFC FFFD |  | #NMI | nicht maskierbarer Interrupt
FFF6 FFF7 |  | #FIRQ | schneller maskierbarer Interrupt
FFF8 FFF9 |  | #IRQ | maskierbarer Interrupt
FFFA FFFB |  | SWI1 | Software-Interrupt1
FFF4 FFF5 |  | SWI2 | Software-Interrupt2
FFF2 FFF3 |  | SWI3 | Software-Interrupt3
FFF0 FFF1 |  |  | (reserviert)

Praktische Übung P1.3-1:
Ergänzen Sie die obenstehende Tabelle 1.3-1 um die Interruptvektoren, die im Festwertspeicher des Praktikumsrechners programmiert sind. Schauen Sie sich dazu jeweils den Beginn der zugehörigen Interruptroutine an !

Treten mehrere Unterbrechungsanforderungen gleichzeitig auf, werden sie nach fest vorgegebenen Prioritäten abgearbeitet. Diese Prioritäten sind in der folgenden Tabelle 1.3-2 angegeben.

Tabelle 1.3-2: Interrupts des 6809, nach Prioritäten geordnet

Priorität | Interrupt | gesetztes Flag im CC Register | gesperrte Interrupts
--- | --- | --- | ---
1 | #NMI | E,F,I | #IRQ, #FIRQ
2 | #FIRQ | -,F,I | #IRQ, #FIRQ
3 | #IRQ | E,-,I | #IRQ
4 | SWI1 | E,F,I | #IRQ, #FIRQ
5 | SWI2 | E,-,- | ----
6 | SWI3 | E,-,- | ----

1.3/6

Eine Zusammenfassung dieses Unterabschnittes enthält das Flußdiagramm im Bild 1.3-3.

Bild 1.3-3: | Flußdiagramm zur Interruptbehandlung |

1.3/7

### 1.3.3 Der Registersatz

Der Registersatz des 6809 wurde bereits im Bild 1.3-1 gezeigt. Hier sollen nun die Register ausführlicher beschrieben werden 9). Tabelle 1.3-3 stellt noch einmal die Register, ihre abkürzende Bezeichnungen und ihre Bitlängen zusammen.

Tabelle 1.3-3: Register der CPU 6809

Bez. | Name | Funktion | Länge
--- | --- | --- | ---
A | Accumulator | 8-bit-Akkumulator | 8 bit
B | Accumulator | 8-bit-Akkumulator | 8 bit
D | Accumulator (A,B) | 16-bit-Akkumulator | 16 bit
PC | Program Counter | Programmzähler | 16 bit
X | Index Register | Indexregister mit Auto-Inkr./Dekr., | 16 bit
Y | Index Register | auch als Universalreg. einsetzbar | 16 bit
U | User Stack Pointer | Stackregister für Benutzer- oder | 16 bit
S | System Stack Pointer | Systemstack, PUSH/PULL-Befehle | 16 bit
DP | Direct Page Register | Seiten-Adreßregister | 8 bit
CC | Condition Code Register | Statusregister | 8 bit

- Akkumulatoren A,B (D)
  sind zwei 8-bit-Register, die bei (fast) allen arithmetischen oder logischen Operationen einen der Operanden und das Ergebnis enthalten. Sie können in einigen Befehlen zu einem 16-bit-Akkumulator D zusammengefaßt werden, wobei dann A das höherwertige und B das niederwertige Byte enthalten. Bei der Multiplikation stehen in A und B die Faktoren und in D das Ergebnis.
- Programmzähler PC
  Der Programmzähler enthält stets die Adresse der Speicherzelle, in der der als nächster auszuführende Befehl oder Befehlsteil steht10).
- Indexregister X,Y
  Dies sind 16-bit-Register (2 byte), die über die Möglichkeit der automatischen Modifikation um den Wert w=1 oder w=2 verfügen:
  - Prädekrement: Vor der Ausführung der Operation wird der Registerinhalt um w erniedrigt,
  - Postinkrement : Nach der Ausführung der Operation wird der Registerinhalt um w erhöht.

  1.3/8

  Sie werden zur Berechnung und Änderung relativer Adressen verwendet (s. nächsten Abschnitt). Damit kann z.B. in einer Tabelle in aufsteigender oder absteigender Reihenfolge mit

  - w=1: das nächste Datenbyte,
  - w=2: das nächste 16-bit-Datenwort (oder die nächste 16-bit-Adresse)
  angesprochen werden.

  Durch die Befehle LEAX (Load Effective Address X) und LEAY (Load Effective Address Y, siehe Abschnitt 1.3.5) kann während der Laufzeit eines Programms die effektive Adresse eines Operanden ermittelt und ins Indexregister X bzw. Y gebracht und dort manipuliert werden. Dies erlaubt - zusammen mit der relativen Adressierung, siehe nächsten Abschnitt - das Schreiben von lageunabhängigen Programmen, die an einem beliebigen Ort im Speicher ablauffähig sind. X und Y können aber auch als allgemeine Datenregister benutzt werden.

- Stackregister S, U
  Das Stackregister S dient zur Verwaltung des Systemstacks, der bei Unterprogramm-Sprüngen und Unterbrechungen von der CPU zur Speicherung der Rücksprungadressen und der internen Register verwendet wird. Über den Systemstack können Haupt- und Unterprogramme aber auch Daten austauschen. S wird durch die Speichervorgänge bei Sprüngen in bzw. Rücksprüngen aus Unterprogrammen und Interruptroutinen sowie durch spezielle Befehle (PSHS/PULS) automatisch modifiziert, und zwar - wie bei den Indexregistern beschrieben - prädekrementell und postinkrementell. Der Stack Pointer U dient zur Verwaltung eines dem Anwender zur freien Verfügung stehenden Benutzerstacks. Dieser Stack wird über die speziellen Befehle PSHU/PULU aufgebaut.
- Seitenadreßregister DP
  Bei der "direkten Adressierung" 11) (s. nächsten Abschnitt) wird die Adresse durch Konkatenation aus dem Wert des DP-Registers und der im Befehl angegebenen 8-bit-Kurzadresse gebildet, wobei der Inhalt des DP-Registers das höherwertige Byte der Adresse ist. Beim RESET wird das DP-Register auf $00 gesetzt. Mit dem DP-Register lassen sich 28=256 Seiten (Pages) ansprechen. Jede Page ist 256 Bytes lang. Damit ergibt sich für die effektive Gesamtadresse:
  EA = (DP)*256 + Kurzadresse.
  Die Vorteile der Adressierung über das DP-Register bestehen in kürzeren und schnelleren Programmen, da für das höherwertige Adreßbyte kein Speicherplatz und für sein Holen aus dem Speicher kein zusätzlicher Zyklus benötigt wird.
- Statusregister CC
  Im Statusregister (Condition Code Register) werden in der Regel Informationen über das Ergebnis arithmetischer oder logischer Operationen gespeichert. Diese Informationen werden insbesondere von Verzweigungsbefehlen ausgewertet.

  1.3/9

  Im folgenden Bild 1.3-4 wird der Aufbau des Statusregisters dargestellt und die Lage der Flags darin gezeigt. Bei ihrer Beschreibung werden wir schon im Vorgriff auf Abschnitt 1.3.5 kurz auf einige Befehle eingehen, bei denen die besprochenen Flags eine besondere Rolle spielen.

  Bit |
  7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
  Bez. |
  E | F | H | I | N | Z | V | C
  Flag |
  Entire | FIRQ- Mask | Half- Carry | IRQ- Mask | Nega- tive | Zero | Over- flow | Carry

  Bild 1.3-4: Die Flags des Statusregisters
- Carry Flag (Bit 0)
  Dieses Flag wird gesetzt, wenn bei Operationen mit zwei Bytes bei Bit 15 und Operationen mit einem Byte bei Bit 7 ein Übertrag entsteht (z.B. bei Additionsbefehlen). Es nimmt ferner bei Schiebe- und Rotationsbefehlen die Information der geschobenen Bits auf. Bei Schiebe- und Rotationsbefehlen nach rechts wird das niederstwertige, nach links das höchstwertige Bit aufgenommen 12). Zusätzlich gelten folgende Bedingungen:
  Der COM-Befehl setzt das C-Flag, der CLR-Befehl löscht das C-Flag. Beim MUL-Befehl wird es gesetzt, wenn Bit 7 im Akkumulator B gesetzt ist. Beim CWAI und ANDCC Befehl nimmt es den Wert der UND-Verknüpfung zwischen den Bits 0 des CC-Registers und der im Befehl angegebenen Konstanten an und beim ORCC-Befehl den Wert der entsprechenden ODER-Verknüpfung.
- Overflow Flag (Bit1)
  Zur Bearbeitung von vorzeichenbehafteten Speicher- oder Registerinhalten wird die Zweierkomplement-Arithmetik angewendet. (Bit 7 gilt dabei als Vorzeichen, wobei "1" mit "-" und "0" mit "+" identifiziert werden.) Dieses Flag wird gesetzt, wenn bei den Befehlen ADD, ADC, CMP, SBC, SUB, DEG, INC und NEG ein Überlauf im Zweier-Komplement auftritt, also eine Zahl größer als 127 ($7F) oder kleiner als -128 ($80) erzeugt wird.
- Zero Flag (Bit 2)
  Dieses Bit zeigt an, daß das Ergebnis einer vorangegangenen Operation Null war.
- Negative Flag (Bit 3)
  Dieses Flag nimmt den Wert des höchstwertigen Bits eines Operationsergebnisses auf. Es bezeichnet durch den Wert 1 eine negative, durch 0 eine positive Zahl.

  1.3/10

- Interrupt Mask (Bit 4)
  Dieses Flag sperrt während der Abarbeitung der Interruptroutine alle weiteren IRQ-Anforderungen. Es wird gesetzt bei der Aktivierung einer der Unterbrechungsan-forderungen #RESET, #NMI, SWI1, #FIRQ, #IRQ, nicht jedoch bei SWI2, SWI3.
- Half-Carry Flag (Bit 5)
  Dieses Flag wird bei Additionsbefehlen gesetzt, wenn ein Übertrag von Bit 3 nach Bit 4 erfolgt oder wenn bei dem Befehl SBC das Bit 7 gesetzt wird.. Es wird z.B. bei der Abarbeitung des Befehls DAA verwendet, der aus einem dualen Rechenergebnis eine BCD-Zahl erzeugt13).
- Fast Interrupt Mask (Bit 6)
  Dieses Flag sperrt den Interrupteingang FIRQ. Es wird gesetzt bei der Aktivierung einer der Unterbrechungsanforderungen #RESET, #NMI, SWI1 und #FIRQ, nicht jedoch bei SWI2 und SWI3.
- Entire Flag (Bit 7)
  Dieses Flag zeigt an, welche Register während des letzten Interrupts im Systemstack gerettet wurden. Ist Bit 7=1, wurden alle Register gerettet; ist es gleich 0, wurde nur das CC-Register und der Program Counter PC abgespeichert. Diese Information wird vom RTI-Befehl (Return from Interrupt) ausgewertet.

1.3/11

### 1.3.4 Die Adressierungsarten

Die Adressierungsarten des 6809 bezeichnen die verschiedenen Möglichkeiten, Operandenadressen, d.h. Befehls- und Datenadressen, aus den 16 bit langen Indexregistern X,Y, den Stackregistern U,S und dem Programmzähler PC zu bilden. Mit Hilfe des 8 bit langen Direct Page Registers DP kann für Kurzbefehle das höherwertige Byte der Adresse fest eingestellt werden14).

Praktische Übung P1.3-2:
Führen Sie die im folgenden als Beispiele angegebenen Befehle bzw. Befehlsfolgen im Praktikumsrechner selbst durch. Geben Sie dazu diese Befehle ab der Startadres-se $0400 ein und beenden Sie die Eingabe durch einen Sprung ins Monitorprogramm mit Hilfe des Software-Interrupts SWI1 ($3F). Schauen Sie sich mit der `Taste R` die Ergebnisse der Befehle in den Registern an und vergleichen Sie sie mit den adressierten Originalwerten im Speicher !
(Zur Initialisierung sind leider einige Register- und Speicherzellen-Zuweisungen nötig, um sinnvolle Ergebnisse zu erzielen. Diese Zuweisungen können Sie über die Tastatur vornehmen. Falls Sie auf die praktische Ausführung der Befehle verzichten, können Sie diese Zuweisungen außer acht lassen und nur die dunkel unterlegten Befehle betrachten.)

Der 6809 unterstützt die im folgenden aufgezählten Adressierungsarten.
(Dabei bedeuten immer: # = immediate ; $ = hex.)

1. Unmittelbare Adressierung (immediate addressing)

Bei der unmittelbaren Adressierung folgt dem Befehlscode eine Konstante von 8 oder 16 bit Länge. Der Befehlscode ist meist 1 byte lang. Insbesondere für Befehle, die das Y-Register ansprechen, folgt aber ein 2. Befehlscode-Byte.

1. Variante:

7 |
Befehlscode
Konstante 1.Byte
(Konstante 2.Byte)
| 0

2. Variante:

7 |
Befehlscode 1. Byte
Befehlscode 2. Byte
Konstante 1.Byte
(Konstante 2.Byte)
| 0

1.3/12

Beispiele:

LDA #$F0 | 86 F0 | Lade Akku A mit $F0
LDX #$1234 | 8E 12 34 | Lade X-Reg. mit $1234
LDY #$ABCD | 10 8E AB CD | Lade Y-Reg. mit $ABCD
SWI1 | 3F | (Sprung in den Monitor)

Beim 6809 wird15) die Möglichkeit, ein oder mehrere Register direkt zu adressieren, zu der unmittelbaren Adressierung gezählt. Dies sind insbesondere die Stackbefehle PUSH/PULL und die Register-Transfer- und -Austausch-Befehle TFR und EXG. Diese Befehle haben folgendes Format:

Befehlscode
Postbyte

Die Bestimmung der Register wird im Postbyte vorgenommen. Dies hat den im folgenden Bild 1.3-5 dargestellten Aufbau. In der Tabelle 1.3-4 ist der Code für die Register des 6809 angegeben.

Befehle PUSH und PULL
b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0
PC | * | Y | X | DP | B | A | CC

PSHS/PULS: * = U PSHU/PULU: * = S

Befehle TFR und EXG
b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0
Quellregister-Code | Zielregister-Code

Bild 1.3-5: Der Aufbau des Postbytes für Register-Befehle

Tabelle 1.3-4: Die Codierung der 6809-Register

Register | Binärcode | Hex-Code
--- | --- | ---
D | 0000 | 0
X | 0001 | 1
Y | 0010 | 2
U | 0011 | 3
S | 0100 | 4
PC | 0101 | 5
A | 1000 | 8
B | 1001 | 9
CC | 1010 | A
DP | 1011 | B

1.3/13

2. Implizite Adressierung (inherent addressing)

Diese Adressierung ist allein durch den Opcode bestimmt. Ein Operand wird nicht benötigt. Der Befehl ist 1 byte lang. (Als Ausnahmen umfassen SWI2 und SWI3 je 2 byte.) Die impliziten Befehle beziehen sich auf die Register A,B,X und auf die Sprungbefehle SWI1, SWI2, SWI3, RTI und RTS.

7 |
Befehlscode
| 0

Beispiel:

DECA | 4A
Erniedrige den Inhalt des Akkumulators A um 1.

3. Erweiterte Adressierung 16) (extended addressing)

Bei dieser Adressierungsart folgt nach dem Opcode die vollständige Adresse. Der Befehl ist mindestens 3 Bytes lang.

7 |
Befehlscode
16-bit-Adresse
| 0

Beispiel:

LDA $1234 | B6 12 34 | Opcode, Adresse
SWI1 | 3F | (zum Monitor)
Der Akkumulator A wird aus der Speicherzelle $1234 geladen.

4. Direkte Adressierung (direct addressing)

Im Falle der direkten Adressierung folgt dem Befehlscode eine Adreßangabe mit 8-bit-Wortlänge. Durch diese Adressierung werden die Adressen $XX00 bis $XXFF direkt angesprochen, wobei XX den Inhalt des DP-Registers bezeichnet. Das DP-Register läßt sich mit dem Transfer-Befehl TFR bzw. Exchange-Befehl EXG laden:

7 |
Befehlscode
Kurzadresse
| 0

Beispiele:
1. (Das DP-Register enthalte den Wert $00).

LDA $EB | 96 EB | OpCode, Kurzadresse
SWI1 | 3F | (zum Monitor)
Lade Akkumulator A mit dem Wert der Zelle $00EB

1.3/14

2.

LDB #$1A | C6 1A | (DP auf $1A
TFR B,DP | 1F 9B | setzen)
LDA <$EB | 96 EB | OpCode, Kurzadresse
........... |  |
LDB #0 | C6 00 | (Restaurieren des DP-Registers
TFR B,DP | 1F 9B | für den Monitor)
SWI1 | 3F | (zum Monitor)
Lade den Akkumulator A mit dem Wert der Speicherzelle $1AEB.

Um diesen Befehl direkt ausführen zu können, muß das DP-Register mit dem H-Byte der Adresse geladen werden. In diesem Beispiel wurde der Transfer-Befehl TFR benutzt. Der Akkumulator B wird zunächst mit dem H-Byte $1A geladen (LDB #$1A). Danach folgt der Transfer ins DP-Register (TFR B,DP). Abschließend wird das DP-Register für das Monitorprogramm restauriert.

Selbsttestaufgabe S1.3-1
Schreiben Sie eine Programmsequenz, die folgende Funktion erfüllt: Lade Akkumulator B mit dem Wert der Zelle $1015. Benutzen Sie die direkte Adressierung und den TFR-Befehl bzw. den EXG-Befehl.

Musterlösung zur Selbsttestaufgabe S1.3-1
LDA #$10 | 86 10 |  |
TFR A,DP | 1F 8B | bzw. EXG A,DP | 1E 8B
LDB <$15 | D6 15 | OpCode, Kurzadresse
LDA #0 | 86 00 |  |
TFR A,DP | 1F 8B |  |
SWI1 | 3F |  |

5. Indizierte Adressierung (indexed addressing, relative Adressierung)

Die effektive Adresse wird durch die Addition des Inhalts eines der Zeigerregister X, Y, S, U mit dem Offset gebildet. Der Offset ist im Zweierkomplement angegeben. Er läßt sich in drei Wertebereiche einteilen und ist vorzeichenbehaftet:

Offset-Länge in bit | hexadezimal | dezimal
5 | $10 - $0F | -16 - +15
8 | $80 - $7F | -128 - +127
16 | $8000 - $7FFF | -32768 - +32767

1.3/15

Ein Befehl besteht aus dem Opcode, dem Postbyte und (gegebenenfalls) dem Offset. (In Ausnahmefällen besteht der Opcode auch aus 2 byte).

7 |
Befehlscode
(2. Befehlscode-Byte)
Postbyte
8- oder 16-bit-Offset
oder Adresse
| 0

Mit dem Postbyte wird das verwendete Pointer Register X, Y, U, S ausgewählt. Im Postbyte sind für den Offset 5 Bits reserviert, wobei das 5. Bit das Vorzeichen des Offsets angibt. Für den Bereich -16 bis +15 ist so kein zusätzliches Befehlsbyte erforderlich. Der Offset kann selbst 2 byte lang sein. Wird ein Registerinhalt als Offset verwendet, so wird auch dieser als vorzeichenbehaftete Zahl interpretiert. Im Bild 1.3-6 ist der Aufbau des Postbytes für die indizierte Adressierung dargestellt. Für die zwei Postbyte-Bits rr ist die im Bild 1.3-6 angegebene Ersetzung vorzunehmen.

a)

kein 5-bit-Offset
b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0
1 | r | r | d/i | Adressierungsart

d/i=0: direkt, d/i=1: indirekt
b)

5-bit-Offset
b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0
0 | r | r | n | n | n | n | n

nnnnn: 5-bit-Offset im Zweierkomplement

Register | rr
X Y U S | 00 01 10 11

Bild 1.3-6: Der Aufbau des Postbytes für die indizierte Adressierung

Die folgende Tabelle 1.3-5 zeigt die verschiedenen Möglichkeiten der indizierten Adressierung. Dabei ist für R wiederum eines der vier Index-/Stackregister X, Y, S, U einzusetzen. Die Codierung der beiden Bits rr finden Sie im obenstehenden Bild 1.3-6. (Zur Erleichterung der Programmierarbeit finden Sie im Anhang A Tabellen, in denen für alle vier Register diese Ersetzungen bereits durchgeführt wurden.)

1.3/16

Tabelle 1.3-5: Die verschiedenen indizierten Adressierungsarten

Lfd. Nr. | Offset | Direkt | X ~ | + # | Indirekt | X ~ | + #
Assembler | Postbyte (Hex) | Assembler | Postbyte(Hex)
1 | kein Offset | ,R | 1rr00100 | 0 | 0 | [,R] | 1rr10100 | 3 | 0
2 | 5-Bit* | n,R | 0rrnnnnn | 1 | 0 | 8-Bit Offset benutzen | / | /
3 | 8-Bit | n,R | 1rr01000 | 1 | 1 | [n,R] | 1rr11000 | 4 | 1
4 | 16-Bit | n,R | 1rr01001 | 4 | 2 | [n,R] | 1rr11001 | 7 | 2
5 | A-Register | A,R | 1rr00110 | 1 | 0 | [A,R] | 1rr10110 | 4 | 0
6 | B-Register | B,R | 1rr00101 | 1 | 0 | [B,R] | 1rr10101 | 4 | 0
7 | D-Register | D,R | 1rr01011 | 4 | 0 | [D,R] | 1rr11011 | 7 | 0
8 | Inc. um1 | ,R+ | 1rr00000 | 2 | 0 | nicht erlaubt | / | /
9 | Inc. um 2 | ,R++ | 1rr00001 | 3 | 0 | [,R++] | 1rr10001 | 6 | 0
10 | Dec. um 1 | ,-R | 1rr00010 | 2 | 0 | nicht erlaubt | / | /
11 | Dec. um 2 | ,--R | 1rr00011 | 3 | 0 | [,--R] | 1rr10011 | 6 | 0
12 | PCR 8-Bit | n,PCR | 1rr01100 1) | 1 | 1 | [n,PCR] | 1rr11100 2) | 4 | 1
13 | PCR 16-Bit | n,PCR | 1rr01101 1) | 5 | 2 | [n,PCR] | 1rr11101 2) | 8 | 2
14 | Extended Indirekt | - | - | - | - | [n] | 1rr11111 2) | 5 | 2

*) Der Offset ist im Postbyte enthalten, deshalb ist das Postbyte binär dargestellt. An der Stelle nnnnn wird der Offset im Binärcode gesetzt und dann in den Hex-Code umgeformt.
1) 1. Tetrade auch: 8, A, C, E
2) 1. Tetrade auch: 9, B, D, F

In der Tabelle wird zwischen der direkt- und der indirekt-indizierten Adressierung unterschieden.

Beispiel zur direkt-indizierten Adressierung:

| X := $1000 | (Initialisierung)
LDA 10,X | A6 0A | OpCode, Postbyte
SWI1 | 3F | (zum Monitor)

Lade den Inhalt der Speicherzelle, deren Adresse sich aus der Summe des Inhalts des X-Registers mit dem Offset (hier dezimal 10) ergibt, in den Akkumulator A.
Der Offset wird hier im Postbyte angegeben, da er im 5-bit-Bereich liegt. (Zur Initialisierung wurde das X-Register mit $1000 geladen.)

Beispiel zur indirekt-indizierten Adressierung:

| X := $1000 | (Initialisierung)
| ($100A,$100B):=$0400 | (Initialisierung)
LDA [10,X] | A6 98 0A | OpCode, Postbyte, Offset
SWI1 | 3F | (zum Monitor)

1.3/17

Die Summe des X-Registers mit dem Offset ergibt die Adresse einer Speicherzelle, in der das H-Byte der Adresse der in den Akkumulator A zu ladenden Speicherzelle steht. Das L-Byte der Adresse steht in der folgenden Speicherzelle. Hier kann der Offset 10 (=$A) nach Tabelle 1.3-5 nicht im Postbyte untergebracht werden. (Zur Initialisierung wurde der Wert $1000 ins X-Register und der Wert $0400 in die Speicherzellen $100A,$100B gebracht.)

Beispiel für einen 4-Byte-Befehl:

| X := $1000 | (Initialisierung)
LDY 20,X | 10 AE 88 14 | Opcode, Postbyte, Offset
SWI1 | 3F | (zum Monitor)

Lade das Y-Register mit dem Inhalt der Speicherzellen, die durch X+20 und X+20+1 angegeben werden. (Zur Initialisierung wurde X auf den Wert $1000 gesetzt.)

Beispiel für einen 5-Byte-Befehl:

| X := $1000 | (Initialisierung)
| Y := $1234 | (Initialisierung)
STY [501,X] | 10 AF 99 01 F5 | Opcode, Postbyte, Offset
SWI1 | 3F | (zum Monitor)

Der Inhalt des Y-Registers ($1234) soll in zwei hintereinanderfolgenden Speicherzellen ($11F5,$11F6) abgelegt werden. Die Adresse der 1. Speicherzelle steht in der Speicherzelle (H-Byte), die durch die Summe aus dem X-Register und dem Offset adressiert wird, sowie in der darauf folgenden Speicherzelle (L-Byte). (Zur Initialisierung wurden die Register X,Y auf geeignete Werte gesetzt.)

Bei den bisherigen Befehlen wurde ein spezieller Offset angeben. Als nächstes werden einige Beispiele gezeigt, bei denen die Akkumulatoren die Offsets liefern. Die effektive Adresse wird wie bei den bisherigen Offset-Typen gebildet. Ein zusätzliches Byte wird nicht benötigt, da in dem Postbyte die Register ausgewählt werden.

Beispiele:

Y := $1000 | B := $10 | (Initialisierung)
LDA B,Y | A6 A5 | Opcode, Postbyte
SWI1 | 3F | (zum Monitor)

Der Inhalt derjenigen Speicherzelle, deren Adresse durch die Summe aus den Inhalten von B und Y gebildet wird, soll in den Akkumulator A geladen werden.

X := $1000 | D := $0500 | (Initialisierung)
STD [D,X] | ED 9B | Opcode, Postbyte
SWI1 | 3F | (zum Monitor)

1.3/18

Der Inhalt des Akkumulators D wird in zwei hintereinanderliegenden Speicherzellen abgelegt. Die Adresse der 1. Zelle steht in der durch die Addition des Akkumulators D zum X-Register adressierten und der folgenden Speicherstelle. (Zur Vorbereitung wurden die Register X, D geeignet initialisiert.)

5a. Indizierte Adressierung mit "Autoinkrement/Autodekrement":

Autoinkrement (Postinkrement)
Nach Selektierung der Adresse des Operanden wird der Wert des benutzten Registers automatisch um 1 bzw. 2 erhöht.

Beispiel:

| D := $1234 | (Initialisierung)
| U := $1000 | (Initialisierung)
STD ,U++ | ED C1 | Opcode, Postbyte
SWI1 | 3F | (zum Monitor)

+ bedeutet "+1",
++ bedeutet "+2".

Speichere den Inhalt des Akkumulators D auf dem Speicherplatz, der durch den Stack Pointer U angegeben wird, und erhöhe danach den Inhalt des Stack Pointers U um 2.

Autodekrement (Prädekrement)
Der Inhalt des ausgewählten Registers wird zunächst um 1 bzw. 2 erniedrigt. Die erniedrigte Adresse ist dann die effektive Adresse.

Beispiel:

| X := $1000 | (Initialisierung)
LDA ,-X | A6 82 | Opcode, Postbyte
SWI1 | 3F | (zum Monitor)

- bedeutet "-1",
-- bedeutet "-2".

Lade den Inhalt derjenigen Speicherzelle in den Akkumulator A, deren Adresse durch den vorher um 1 verminderten Wert des X-Registers angegeben wird.

Eine weitere Möglichkeit der indizierten Adressierung besteht in der relativen Adressenbildung mit Hilfe des Program Counters (PC-relative Adressierung). Durch Addition des Program Counters mit einem vorzeichenbehafteten 8- bzw. 16-bit-Offset wird die Adresse gebildet. Hierzu werden bei einem 8-bit-Offset ein zusätzliches Byte, bei einem 16-bit-Offset zwei zusätzliche Bytes benötigt.

Beispiel:

SUBD $1000,PC | A3 8D 10 00, | Opcode, Postbyte, Offset
SWI1 | 3F | (zum Monitor)

1.3/19

Vom Inhalt des Akkumulators D wird der Inhalt derjenigen Speicherzelle subtrahiert, deren Adresse durch die Addition des Offsets zum PC gegeben ist.

Die erweiterte (extended) indirekte Adressierung ermöglicht eine relative Adressierung mit Hilfe von 2 zusätzlichen Bytes.

Beispiel:

| ($1234,$1235):=$1000 | (Initialisierung)
LDB [$1234] | E6 9F 12 34 | Opcode, Postbyte, Offset
SWI1 | 3F | (zum Monitor)

Lade den Inhalt der Speicherzelle, deren Adresse in der Speicherzelle $1234, $1235 steht, in den Akkumulator B.

6. PC-Relative Adressierung bei Verzweigungsbefehlen

Die PC-relative Adressierung wird beim 6809 insbesondere für Verzweigungsbefehle benötigt. Die Darstellung des Offsets geschieht im Zweierkomplement, wobei das höchstwertige Bit das Vorzeichen festlegt: "0" = "+", "1" = "-". Bei einigen Prozessoren wird bei der PC-relativen Adressierung mit einem Offset von einem Byte gearbeitet, so daß Sprünge im Bereich von +127 und -128 möglich sind. Mit dem 6809 ist es jedoch möglich, zu jeder Adresse im Speicher zu verzweigen. Hierzu werden der Opcode sowie der Offset auf jeweils 2 Bytes erweitert, so daß sich insgesamt 4-byte-Befehle ergeben. Der Sprungbereich beträgt somit -32768 bis 32767.

Wichtig:
Ausgangspunkt für die Berechnung des Offsets ist immer die Adresse des OpCodes des 1. Befehls nach dem Verzweigungsbefehl! Die Distanz ergibt sich als Differenz zur Adresse, unter der der OpCode des Zielbefehls steht.

Short Branch:

7 |
Befehlscode
Offset
| 0

Long Branch:

7 |
Befehlscode
Befehlscode
Offset
Offset
| 0

Beispiel:

BMI -12 | 2B F4 | Rücksprung um -12
LBMI 2020 | 10 2B 07 E4 | Vorwärtssprung um +2020

1.3/20

Ist im Statusregister das N-Flag (Negative Flag) gesetzt, so werden diese relativen Sprünge ausgeführt. Beim BMI wird der PC um $F4 erniedrigt, beim LBMI um $07E4 erhöht.

Das folgende Bild 1.3-6 zeigt die verschiedenen Möglichkeiten der Adressenbildung im Zusammenhang. Darin bedeuten:

EA | effektive Adresse, | DP | Direct Page Register,
A | Akkumulator A, | X | Indexregister
und die Nummern 1- 5 bezeichnen die folgenden Befehle:

1 | LDA #$30 |
2 | LDA <$30 | : EA=256*DP+$30
3 | LDA 18,X | : EA=$AF00+$12
4 | LDA $8FD6 | : EA=$8FD6
5 | LDA [10,X] | : EA=[$AF00+$A]*256+[$AF00+$A+1]

Bild 1.3-6: | Gesamtübersicht zur Adressenbildung |

1.3/21

### 1.3.5 Der Befehlssatz

Der Befehlssatz des 6809 mit seinen Befehlsarten ist im Kapitel 4 des Buches [ZAK84], das dem Praktikumsrechner beigelegt ist, erläutert. Anhand dieses Buches müssen Sie sich nun mit dem Befehlssatz des 6809 auseinander setzen 1). Als Ergänzung werden in diesem Abschnitt zu den einzelnen Befehlsarten nur einige Beispiele gebracht, die das Arbeiten mit den im Anhang B aufbereiteten Tabellen erleichtern sollen. In diesen Tabellen finden Sie matrixförmig angeordnet - zeilenweise die verschiedenen Befehle, in den Spalten die unterstützten Adressierungsarten eingetragen. Die fast vollständig ausgefüllten Tabellen zeigen einen der Punkte, die den 6809 zum sicher besten 8-bit-Prozessor machen: Der Befehlssatz ist nahezu orthogonal.

Für jede Spalte, also jede Adressierungsart, ist in der 1. Unterspalte der OpCode eingetragen. Er ist für die meisten Befehle 1 byte lang. Hauptsächlich für Befehle, die die Register Y, U, S und z.T. auch D betreffen, ist der OpCode 2 byte lang. Das 1. Byte ist dabei stets $10 oder $11 2). In der 2. Unterspalte, gekennzeichnet durch "", ist die Anzahl der Maschinenzyklen angegeben, die die Befehlsabarbeitung dauert. Die 3. Unterspalte gibt die Anzahl der Bytes an, die der Befehl im Speicher belegt. In beiden Fällen muß für die indizierte Adressierungart noch die Anzahl der Maschinenzyklen und Befehlsbytes hinzugezählt werden, die in der Tabelle 1.3-5 angegeben sind. Die vorletzte Spalte gibt für jeden Befehl eine kurze, formelmäßige Beschreibung, bei den Schiebe- und Rotationsbefehlen eine kleine Skizze. In der letzten Spalte wird angezeigt, wie jeder Befehl auf die Flags im Statusregister wirkt. Dabei wird insbesondere unterschieden, ob das Flag unverändert bleibt (""), seinen Zustand ändert ("|") oder auf "0" gesetzt wird. Diese Angaben müssen Sie bei den verlangten Programmen sehr sorgfältig beachten, da sonst "Seiteneffekte" drohen 3).

Bei der folgenden Beschreibung der Befehle wird die alphabetische Reihenfolge der Befehle genommen. Ausgenommen davon sind die Branch-Befehle, die am Ende dieses Abschnittes beschrieben werden. (Durch das Zeichen "/" werden in der folgenden Beschreibung die verschiedenen Befehls- und Registervarianten voneinander getrennt.)

Praktische Übung P1.3-3:
Führen Sie die folgenden Befehle (oder wenigstens einige von Ihnen) mit Ihrem Praktikumsrechner durch. Initialisieren Sie die benutzten Register durch geeignete Parameter und benutzen Sie die Trace-Funktion (`Taste T`) zur Einzelschrittausführung der Befehle!

1.3/22

ABX (Add Accumulator B into Index Register X)
Der Inhalt des Akkumulators B wird vorzeichenlos zum Inhalt des X-Registers addiert. Das Ergebnis steht im X-Register. Das CC-Register wird durch diese Operation nicht beeinflußt.

ABX |  | 3A

ADCA/ADCB (Add with Carry into Register A/B)
Zum Inhalt des Akkumulators A bzw. B wird das Carry Flag und der Inhalt einer Speicherzelle oder eine Konstante addiert. Das Ergebnis wird in den Akkumulator A bzw. B geschrieben.

ADCA | #$10 | 89 10
ADCB | 10,X | E9 0A

ADDA/ADDB/ADDD (Add Memory into Register A/B/D)
Zum Inhalt des ausgewählten Registers wird der Inhalt einer Speicherzelle oder eine Konstante addiert. Beim 16-bit-Akkumulator D sind es zwei aufeinander folgende Speicherzellen bzw. eine 2-byte-Konstante.

ADDA | #$10 | 8B 10
ADDB | 10,X | EB 0A

ANDA/ANDB/ANDCC (Logical AND Memory into Register A/B/CC)
Der Inhalt von A bzw. B wird mit dem Inhalt einer Speicherzelle oder eine Konstante (logisch) UND-verknüpft. Das Ergebnis wird in A bzw. B geschrieben. Das Carry Flag und das Halfcarry Flag werden nicht beeinflußt. Das Overflow Flag wird gelöscht.
Beim CC-Register kann eine Verknüpfung ausschließlich mit einer Konstanten erfolgen. Das Ergebnis der Operation steht im CC-Register. Dies ist die einzige Möglichkeit beim 6809, bestimmte Flags des CC-Registers zu setzen, rückzusetzen oder abzufragen. (Spezielle Flag-Befehle wie bei anderen Prozessoren gibt es hier nicht.)

ANDA | $EB | 94 EB
ANDB | $1243 | F4 12 43
ANDCC | #$AA | 1C AA

ASL/ASLA/ASLB (Arithmetic Shift Left)
Jedes Bit der Speicherzelle bzw. des Akkumulators A/B wird um eine Position nach links verschoben. Bit 0 wird auf '0' gesetzt. Bit 7 wird ins Carry Flag geschoben. Das Overflow Flag erhält das Ergebnis der XOR-Verküpfung von Bit 6 und Bit 7. Das Carry Flag erhält den ursprünglichen Wert von Bit 7.

ASLA |  | 48
ASLB |  | 58
ASL | [10,Y] | 68 B8 0A

1.3/23

ASR/ASRA/ASRB (Arithmetic Shift Right)
Jedes Bit der Speicherzelle bzw. des Akkumulators A/B wird um eine Position nach rechts verschoben. Bit 0 wird ins Carry Flag geschoben. Bit 7 bleibt unverändert:

ASRA |  | 47
ASRB |  | 57
ASR | $1234 | 77 12 34

BITA/BITB (Bit Test)
Der Inhalt von A/B wird mit dem Inhalt einer Speicherzelle oder eine Konstante logisch bitweise UND verknüpft, wobei die Inhalte des Akkumulators A/B und der Speicherzelle nicht verändert werden. Das Ergebnis beeinflußt nur das CC-Register. Das Overflow Flag wird gelöscht. Carry Flag und Halfcarry Flag werden nicht geändert.

BITA | #$55 | 85 55
BITB | $EE | D5 EE

CLR/CLRA/CLRB (Clear)
Der Inhalt der Speicherzelle bzw. des Akkumulators A/B wird gelöscht, d.h. auf den Wert $00 gesetzt. Das Zero Flag wird gesetzt. Negative, Overflow und Carry Flag werden gelöscht.

CLRA |  | 4F
CLRB |  | 5F
CLR | 13124,Y | 6F A9 33 44

CMPA/CMPB/CMPD/CMPS/CMPU/CMPX/CMPY (Compare Memory)
Der Inhalt von A/B/D/S/U/X/Y wird mit dem Inhalt einer bzw. zweier Speicherzelle(n) oder eine 1-byte- bzw. 2-byte-Konstante verglichen. Der Vergleich wird durch eine Subtraktion durchgeführt. Die Register bzw. die Speicherzelle(n) werden nicht verändert. Abhängig vom Ergebnis der Subtraktion werden die entsprechenden Flags im CC-Register gesetzt. Dieser Befehl dient in der Regel dazu, die Vorausetzungen für eine bedingte Verzweigung abzuprüfen.

CMPA | #$AA | 81 AA
CMPB | $AA | D1 AA
CMPD | 13124,S | 10 A3 E9 33 44
CMPS | 10,U | 11 AC 4A
CMPU | $1234 | 11 B3 12 34
CMPX | [13124,U] | AC D9 33 44
CMPY | [D,U] | 10 AC DB

COM/COMA/COMB (Complement)
Der Inhalt der Speicherzelle bzw. des Akkumulators A/B wird durch das Einerkomplement ersetzt. Das Overflow Flag wird gelöscht, und das Carry Flag wird gesetzt.

1.3/24

COMA |  | 43
COMB |  | 53
COM | $1234 | 73 12 34

CWAI (Clear CC-Flags and Wait for Interrupt)
Das CC-Register wird mit der nachfolgenden Konstanten logisch UND-verknüpft. Das Ergebnis wird in das CC-Register geschrieben. Anschließend wird das E-Flag gesetzt und auf einen Hardware-Interrupt gewartet. Bis zur Interruptauslösung wird kein weiterer Befehl abgearbeitet.

CWAI | 3C xx | xx
| : | FF : | FIRQ und IRQ | gesperrt
| EF : | FIRQ | gesperrt
| BF : | IRQ | gesperrt
| AF : | kein Interrupt | gesperrt

DAA (Decimal Addition Adjust)
Da bei arithmetischen Operationen mit BCD-Zahlen unerwünschte Ziffern zwischen $A und $F entstehen können, kann mit Hilfe des DAA-Befehls eine Korrektur dieser Zahlen vorgenommen werden, so daß im Akkumulator A wieder eine gültige BCD-Zahl steht. Beispiel:

LDA | #$67 | 86 67 | BCD-Zahl 67
ADDA | #$75 | 9B 75 | BCD-Zahl 75
|  |  | "falsches" Ergebnis = $DC
DAA |  | 19 | "korr." Ergebnis = 142
|  |  | C-Flag = 1, Akku A = $42

DEC/DECA/DECB (Decrement)
Der Inhalt der Speicherzelle bzw. des Akkumulators A/B wird um 1 erniedrigt. Das Carry Flag und das Half-Carry Flag werden nicht beeinflußt. Das Overflow Flag wird nur gesetzt, wenn der Inhalt vorher $80 war, da der neue Wert $7F einen Vorzeichenwechsel (zum "+") bedeutet.

DECA |  | 4A
DECB |  | 5A
DEC | $AA | 0A AA

EORA/EORB (Logical EXOR Memory into Register)
Der Inhalt des Akkumulators A/B wird mit dem Inhalt einer Speicherzelle oder eine Konstante logisch bitweise exklusiv-ODER-verknüpft. Das Ergebnis steht in Akku-mulator A/B.

EORA | #$FF | 88 FF
EORB | $1234 | F8 12 34

1.3/25

EXG (Exchange Register)
Der Befehl ermöglicht den Austausch zweier Registerinhalte, wobei ein Austausch nur unter Registern gleicher Länge zulässig ist. Die Register werden durch das Postbyte ausgewählt. Die Bits 0-3 enthalten die Kennung des zweiten, die Bits 4-7 die des ersten Registers nach folgender Codierung (vgl. Tabelle 1.3-4):

A | = 1000, | PC | = 0101,
B | = 1001, | U | = 0011,
D | = 0000, | S | = 0100,
X | = 0001, | CC | = 1010,
Y | = 0010, | DP | = 1011,

EXG | A,B | 1E 89 | ($89=10001001)

INC/INCA/INCB (Increment)
Der Inhalt einer Speicherzelle bzw. des Akkumulators A/B wird um 1 erhöht. Das Overflow Flag wird gesetzt, wenn die Zahl vorher den Wert $7F hatte, da der erhöhte Wert $80 einen Vorzeichenwechsel (zum "-") darstellt.

INCA |  | 4C
INCB |  | 5C
INC | 10,X | 6C 0A

JMP (Jump)
Der Program Counter PC wird mit der effektiven Adresse geladen, die sich aus den dem Opcode folgenden 1-3 Bytes ergibt. Dadurch wird ein unbedingter Sprung zu einer neuen Programmstelle durchgeführt.

| Sprungadresse
JMP | $50 | 0E 50 | DP*256+$0050
JMP | $1234 | 7E 12 34 | $1234
JMP | A,X | 6E 86 | X+A

JSR (Jump to Subroutine)
Der JSR-Befehl erwirkt einen Sprung in ein Unterprogramm, wobei die Rücksprungadresse im Systemstack abgespeichert wird. Besonders wichtig ist dabei die Möglichkeit der indizierten Adressierung, auch der indirekten indizierten Adressierung. Hierdurch ist es insbesondere möglich, zur Laufzeit eines Programmes z.B. Tabellen von Einsprungadressen der Unterprogramme zu berechnen.

JSR | $1234 | BD 12 34
JSR | A,S | AD E6
JSR | [$6F,PCR] | AD 9C 6F

1.3/26

LDA/LDB/LDD/LDS/LDU/LDX/LDY (Load Register from Memory)
Das Register A/B wird mit dem Inhalt einer Speicherzelle oder mit einer Konstanten geladen. Bei den Registern D/S/U/X/Y wird der Inhalt zweier Speicherzellen oder eine 2-byte-Konstante geladen. Das Overflow Flag wird gelöscht.

LDA | #$FF | 86 FF
LDB | $AA | D6 AA
LDD | 10,X | EC 0A
LDS | #$1234 | 10 CE 12 34
LDU | #$11 | CE 11
LDX | $0A | 9E 0A
LDY | [13124,X] | 10 AE 99 33 44

LEAS/LEAU/LEAX/LEAY (Load Effective Address)
Es wird die effektive Adresse einer Speicherzelle, die durch den Offset und den Inhalt eines Registers nach der im Postbyte bestimmten Adressierungsart gebildet wird, in das angegebene Register geladen. Dieser Befehl erlaubt es, zur Laufzeit eines Programmes die Adresse eines Operanden zu bestimmen und weiter zu verarbeiten. Sehr wichtig sind auch die beiden erstgenannten Beispielbefehle zum Aufbau von Schleifenvariablen. (Aber Vorsicht: LEAX ,X+ tut nicht, was er soll !)

LEAX | 1,X | 30 01
LEAY | ,-Y | 31 A2
LEAS | ,X | 32 84
LEAU | B,X | 33 85
LEAX | [13124,Y] | 30 B9 33 44
LEAY | [D,S] | 31 FB

LSL/LSLA/LSLB (Logical Shift Left)
Jedes Bit der Speicherzelle bzw. des Akkumulators A/B wird um eine Position nach links verschoben. Bit 0 wird auf '0' gesetzt, und Bit 7 wird ins Carry Flag geschoben. Das Overflow Flag nimmt den Wert der EXOR-Verknüpfung von Bit 7 und Bit 6 an.

LSLA |  | 48
LSLB |  | 58
LSL | $12 | 08 12

LSR/LSRA/LSRB (Logical Shift Right)
Jedes Bit der Speicherzelle bzw. des Akkumulators A/B wird um eine Position nach rechts verschoben. Bit 7 wird auf '0' gesetzt, und Bit 0 wird ins Carry Flag übertragen.

LSRA |  | 44
LSRB |  | 54
LSR | 20,X | 64 88 14

1.3/27

MUL (Multiply)
Der Inhalt von Akkumulator A wird mit dem Inhalt von Akkumulator B multipliziert. Das Ergebnis wird in D geschrieben (A höherwertiges, B niederwertiges Byte). Das Carry Flag erhält den Inhalt des Bits 7 von B nach Beendigung der Operation.

MUL |  | 3D

NEG/NEGA/NEGB (Negate)
Der Inhalt der Speicherzelle bzw. des Akkumulators A/B wird durch sein Zweierkomplement ersetzt. Das Overflow Flag wird nur gesetzt, wenn der Inhalt vor Ausführung $80 war. Das Carry Flag wird nur dann nicht gesetzt, wenn der Inhalt vor der Ausführung $00 war.

NEGA |  | 40
NEGB |  | 50
NEG | $AA | 00 AA

NOP (No Operation)
Der Program Counter wird um 1 erhöht. Alle Bedingungs-Flags bleiben unverändert 4).

NOP |  | 12

ORA/ORB/ORCC (Logical OR into Register)
Der Inhalt des Registers A/B wird mit dem Inhalt einer Speicherzelle oder eine Konstante, der Inhalt des CC-Registers nur mit einer Konstanten logisch ODER-verknüpft. Die Verknüpfung wird bitweise vorgenommen. Das Ergebnis steht im angegebenen Register. Das Overflow Flag wird gelöscht.

ORA | $AA | 9A AA
ORB | $1234 | FA 12 34
ORCC | #$11 | 1A 11

PSHS/PSHU (Push Register on Stack)
PULS/PULU (Pull Register from Stack)
Alle im Postbyte angegebenen Register werden im Stack gespeichert bzw. aus dem Stack gelesen. Beim Abspeichern wird zunächst das betreffene Stackregister S oder U um 1 erniedrigt (prädekrement). Mit dieser Adresse beginnt die Abspeicherung in der Reihenfolge, daß zunächst das höchste Bit (Bit 7) abgefragt wird und das zugehörige Register ggf. in den Stack gebracht wird.
Das Einlesen vom Stack erfolgt in umgekehrter Reihenfolge, d.h. es wird zunächst das Bit 0 geprüft, das entsprechende Register ggf. geladen und das Stackregister erhöht (postdekrement). Danach wird mit den anderen Registern in aufsteigender Bitfolge des Postbytes weitergemacht.

1.3/28

Für beide Stacks U bzw. S gibt es ein eigenes Paar von Befehlen. Das dem Bit 6 im Postbyte zugeordnete Register ist jeweils das Stackregister des durch den Befehl nicht angesprochenen Stacks.

Push/Pull Postbyte:
b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0
PC | * | Y | X | DP | B | A | CC

PSHS/PULS: *=U PSHU/PULU: *=S

PSHU | #$88 | 36 88 | (10001000)
PULU | #$88 | 37 88 | (10001000)
PSHS | #$FF | 34 FF | (11111111)
PULS | #$FF | 35 FF | (11111111)

ROL/ROLA/ROLB (Rotate Left)
Jedes Bit der Speicherzelle bzw. des Akkumulators A/B wird um eine Position nach links verschoben. Bit 7 wird ins Carry Flag, das Carry Flag in Bit 0 geschoben. Das Overflow Flag erhält die EXOR-Verknüpfung der ursprünglichen Werte von Bit 7 und Bit 6.

ROLA |  | 49
ROLB |  | 59
ROL | $1F | 09 1F

1.3/29

ROR/RORA/RORB (Rotate Right)
Jedes Bit der Speicherzelle bzw. des Akkumulators A/B wird um eine Position nach rechts verschoben. Bit 0 wird ins Carry Flag, das Carry Flag ins Bit 7 geschoben. Das Overflow Flag wird nicht beeinflußt.

RORA |  | 46
RARB |  | 56
ROR | 10,X | 66 0A

RTI (Return from Interrupt)
Mit diesem Befehl wird das Interruptprogramm beendet und die Register werden vom Systemstack eingelesen. Ist das E-Bit im CC-Register gesetzt, werden alle Register restauriert. Im anderen Falle werden nur der Program Counter und das CC-Register geladen.

RTI |  | 3B

RTS (Return from Subroutine)
Dieser Befehl beendet das aufgerufene Unterprogramm. Die Rücksprungadresse wird aus dem Systemstack gelesen, und das aufrufende Programm wird an dieser Adresse fortgeführt 5).

RTS |  | 39

1.3/30

SBCA/SBCB (Subtract with Borrow)
Vom Inhalt des Akkumulators A/B wird das Carry Flag und der Inhalt einer Speicherzelle oder eine Konstante subtrahiert.

SBCA | #$1F | 82 1F
SBCB | [13124,X] | E2 99 33 44

SEX (Sign Extend)
Ein im Akkumulator B stehender, 8 bit langer Zweierkomplementwert wird unter Beachtung des Vorzeichens in einen 16 bit langen Wert im Akkumulator D umgewandelt. Ist Bit 7 von B gesetzt, wird in A der Wert $FF, im anderen Fall $00 geschrieben.

SEX |  | 1D

STA/STB/STD/STS/STU/STX/STY (Store in Memory)
Der Inhalt des Registers wird in die angegebene Speicherzelle, bei 16-bit-Registern auch in die nachfolgende Zelle geschrieben. Das Overflow Flag wird gelöscht.

STA | $1F | 97 1F
STB | ,X | E7 84
STD | $201F | FD 20 1F
STS | [D,X] | 10 EF 9B
STU | ,-X | EF 82
STX | $A00A | BF A0 0A
STY | 20,X | 10 AF 88 14

SUBA/SUBB/SUBD (Subtract Memory from Register)
Vom Inhalt des Akkumulators A/B/D wird der Inhalt einer Speicherzelle oder eine Konstante subtrahiert; beim Akkumulator D der Inhalt zweier aufeinander folgender Speicherzellen bzw. eine 2-byte-Konstante.

SUBA | #$AA | 80 AA
SUBB | $EB | D0 EB
SUBD | $1234 | B3 12 34

SWI1/SWI2/SWI3 (Software Interrupt)
Bei diesen Befehlen werden zunächst alle Registerinhalte der CPU in den Systemstack abgespeichert und das E-Flag im CC-Register gesetzt 6). Der SWI1 sperrt zusätzlich den #FIRQ und #IRQ durch Setzen des I- und F-Flags im CC-Register. Anschließend wird die Startadresse des Unterbrechungsprogrammes geladen. (Siehe hierzu in Tabelle 1.3-1.)

SWI1 |  | 3F
SWI2 |  | 10 3F
SWI3 |  | 11 3F

1.3/31

SYNC (Synchronize to External Event)
Der Befehl stoppt die Befehlsabarbeitung, d.h. der Prozessor hält an und wartet auf einen Hardware-Interrupt. Ist der betreffene Interrupt gesperrt (durch Setzen des entsprechenden Flags im CC-Register) oder das Interrupt-Signal kürzer als 3 Taktzyklen, wird die nach dem SYNC-Befehl folgende Sequenz abgearbeitet. Der Interrupt muß also, damit er abgearbeitet werden kann, mindestens 3 Taktzyklen lang anliegen und darf nicht maskiert sein. Dieser Befehl bietet die Möglichkeit der Synchronisation zwischen der Software und der Hardware.

SYNC |  | 13

Beispiel:

LOOP: | SYNC |
| Hardware- Load Store Abfrage: wenn nicht: | Interrupt vom Gerät Daten vom Gerät Daten zum Gerät Datenübertragung beendet? Branch to LOOP

TFR (Transfer Register to Register)
Mit diesem Befehl können Daten vom einem Register in ein anderes übertragen werden. Die Quelle ist das Register, in dem die Daten stehen. Das Ziel ist das Register, das die Daten aufnehmen soll. Quelle und Ziel werden im Postbyte angeben. Die Codierung der Register wurde bereits in Tabelle 1.3-4 angegeben.

Transfer-Postbyte:
b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0
Quelle | Ziel

Anmerkung: Es können nur 8-bit-Registerinhalte in 8-bit-Register und 16-bit-Registerinhalte in 16-bit-Register übertragen werden !

TFR | X,Y | 1F 12

TST/TSTA/TSTB (Test)
Dieser Befehl testet den Inhalt einer Speicherzelle bzw. des Akkumulators A/B auf den Wert $00, positive oder negative Werte. Das Overflow Flag wird gelöscht und das Zero bzw. Negative Flag im CC-Register entsprechend dem Ergebnis gesetzt.

TSTA |  | 4D
TSTB |  | 5D
TST | $1F | 0D 1F

1.3/32

### Branch Befehle (Verzweigungsbefehle bzw. Sprungbefehle)

Ein Branch-Befehl (Verzweigungsbefehl) wird in der Regel dann ausgeführt, wenn der Test der Flags im Condition Code Register CC die für eine bestimmte Verzweigung erforderliche Bedingung erfüllt. Ausnahmen sind hier BRA (Branch Always), BRN (Branch Never) und BSR (Branch to Subroutine). Die Zieladressen der Verzweigungsbefehle werden immer Programmzählerrelativ berechnet, d.h. sie ergeben sich wie folgt:

PC := PC + Offset

Für alle Branch-Befehle existiert die Möglichkeit, einen 1-byte-Offset oder einen 2-byte-Offset anzugeben. Im 2. Fall kann der gesamte Adreßraum von 64kbyte übersprungen werden. Der OpCode ist dabei ebenfalls 2 byte lang.

BRA/LBRA (Branch Always)
Es wird unbedingt zu der Adresse gesprungen, die sich durch Addition des Program Counters mit dem Offset ergibt. Der Unterschied zum JMP-Befehl besteht darin, daß hier keine absolute Sprungziel-Adresse, sondern ein Offset angegeben wird. (Dadurch ist wieder eine lageunabhängige Programmierung möglich.)

BRA | $AA | 20 AA
LBRA | $1234 | 16 12 34

BRN/LBRN (Branch Never)
Es wird kein Sprung ausgeführt. Diese Befehle werden als NOP-Befehle eingesetzt und ermöglichen eine Verlängerung des Programmzweiges um 3 bzw. 5 CPU-Zyklen (Dauer des NOP-Befehls: 1 CPU-Zyklus). Sie können aber auch zu Testzwecken zunächst im Programm untergebracht werden und dann durch andere Branch-Befehle überschrieben werden.

BRN | $11 | 21 11
LBRN | $1234 | 10 21 12 34

BSR/LBSR (Branch to Subroutine)
Vor Abarbeitung des Befehls wird der Inhalt des Program Counters (Adresse des 1. OpCodes nach dem BSR-Befehl) mit Hilfe des Stackregisters S auf den Systemstack geschrieben. Diese Adresse wird vom Rücksprungbefehl RTS benötigt! Die Unterprogrammadresse berechnet sich aus dem Inhalt des Program Counters und dem Offset.

BSR | $AB | 8D AB
LBSR | $1234 | 17 12 34

1.3/33

A. Einfache Verzweigungen

Wird durch einen Verzweigungsbefehl nur eine Bedingung (Flag) im Condition Code Register CC abgefragt bzw. getestet, spricht man von einer einfachen bedingten Verzweigung. Abgefragt werden das N-, Z-, V- oder C-Flag des CC-Registers.

BMI/LBMI (Branch on Minus)
Es wird ein relativer Sprung ausgeführt, wenn das N-Flag im CC-Register gesetzt ist (N="1"). Die Sprungadresse ergibt sich durch Addition des Program Counters mit dem Offset.

BMI | $10 | 2B 10
LBMI | $ABCD | 10 2B AB CD

BPL/LBPL (Branch on Plus)
Es wird ein relativer Sprung ausgeführt, wenn das N-Flag im CC-Register gelöscht ist (N="0").

BPL | $FF | 2A FF
LBPL | $5566 | 10 2A 55 66

BEQ/LBEQ (Branch on Equal)
Es wird ein relativer Sprung ausgeführt, wenn im CC-Register das Z-Flag gleich "1" ist, d.h. das Resultat einer Operation gleich Null war.

BEQ | $01 | 27 01
LBEQ | $1122 | 10 27 11 22

BNE/LBNE (Branch on NOT Equal)
Es wird ein relativer Sprung ausgeführt, wenn das Z-Flag den Wert "0" hat, d.h. das Ergebnis einer Operation war größer oder kleiner als Null.

BNE | $21 | 26 21
LBNE | $0102 | 10 26 01 02

BVS/LBVS (Branch on Overflow Set)
Es wird ein relativer Sprung ausgeführt, wenn das Overflow Flag im CC-Register gesetzt wurde (V=1). Bei der Zweierkomplement-Arithmetik wird beim Überschreiten des Zahlenbereiches (negativ: $80-$FF, positiv: $00-$7F) in negativer oder in positiver Richtung das Overflow Flag gesetzt.

BVS | $10 | 29 10
LBVS | $3001 | 10 29 30 01

BVC/LBVC (Branch on Overflow Clear)
Es wird ein relativer Sprung ausgeführt, wenn die Bedingung V="0" erfüllt ist, d.h. das Overflow Flag gelöscht ist. Dies ist der Fall, wenn bei der Zweierkomplement-Arithmetik der Zahlenbereich nicht überschritten wird.

1.3/34

BVC | $A0 | 28 A0
LBVC | $A0A1 | 10 28 A0 A1

BCS/LBCS (Branch on Carry Set)
Es wird ein relativer Sprung ausgeführt, wenn das Carry Flag im CC-Register gesetzt ist (C="1"), d.h. z.B., daß ein Übertrag bei einer Operation entstanden ist.

BCS | $BB | 25 BB
LBCS | $1234 | 10 25 12 34

BCC/LBCC (Branch on Carry Clear)
Es wird ein relativer Sprung ausgeführt, wenn das Carry Flag den Wert "0" hat. (Achtung: Folgende Befehle invertieren den Wert des Carry Flags: SUB, SBC, CMP.)

BCC | $EF | 24 EF
LBCC | $ABCD | 10 24 AB CD

B. Verzweigungen mit verknüpften Bedingungen

Bei den nachfolgenden Branch-Befehlen werden die Sprungentscheidungen aus logischen Verknüpfungen verschiedener Flags des CC-Registers abgeleitet. Die Verknüpfungen bekommen ihre besondere Bedeutung im Zusammenhang mit dem CMP-Befehl. Bei den ersten vier Verzweigungen werden die Operanden dieses Befehls als vorzeichenbehaftete Zahlen im Zweierkomplement, bei den letzten vier als vorzeichenlose positive Zahlen betrachtet. Mit v bzw. (xor) bezeichnen wir darin stets die logische ODER-Verknüpfung bzw. die Antivalenz. M bzw. R stehen für die 8- bzw- 16-bit-Operanden von CMP im Speicher oder einem der Register.

a) Vorzeichenbehaftete Operanden

M,R aus {-128,..,127} bzw. M,R aus {-32768,..,32767}.

BLT/LBLT (Branch on Less Than)
Es wird ein relativer Sprung ausgeführt, wenn die Bedingung N (xor) V = 1 gilt, d.h. das N-Bit oder das V-Bit ist gesetzt aber nicht beide gleichzeitig. Dies ist der Fall für: R < M.

BLT | $BB | 2D BB
LBLT | $CDEF | 10 2D CD EF

BLE/LBLE (Branch on Less than or Equal to)
Es wird ein relativer Sprung ausgeführt, wenn die Bedingung Zv(N(xor)V)=1 erfüllt ist. Dies ist dann der Fall, wenn entweder das N- oder das V-Flag, nicht jedoch beide, oder das Z-Flag gesetzt ist. Dem entspricht: R < M.

BLE | $45 | 2F 45
LBLE | $1011 | 10 3F 10 11

1.3/35

BGT/LBGT (Branch on Greater than)
Es wird ein relativer Sprung ausgeführt, wenn die Bedingung Zv(N(xor)V)=0 erfüllt ist. In diesem Fall ist das Ergebnis der Operation größer Null (Z=0) und die XOR-Verknüpfung des N- und V-Flags hat den Wert "0", d.h. das N- und das V-Flag sind beide gesetzt oder gelöscht. Hier ist: R > M.

BGT | $11 | 2E 11
LBGT | $1234 | 10 2E 12 34

BGE/LBGE (Branch on Greater than or Equal to)
Es wird ein relativer Sprung ausgeführt, wenn die Bedingung N(xor)V=0 gilt, d.h. wenn das N-Flag und das V-Flag beide gesetzt oder gelöscht sind. Es gilt: R < M.

BGE | $20 | 2C 20
LBLE | $1221 | 10 2C 12 21

b) Vorzeichenlose Operanden

M,R aus {0,..,255} bzw. M,R aus {0,..,65535}

BLO/LBLO (Branch on LOwer)
Es wird ein relativer Sprung ausgeführt, wenn im CC-Register das Carry Flag gesetzt ist (C="1"). Dieser Befehl ist identisch mit dem Befehl BCS (Branch on Carry Set). Es gilt: R < M.

BLO | $77 | 25
LBLO | $7788 | 10 25 77 88

BLS/LBLS (Branch on Lower or Same)
Die Bedingung für einen relativen Sprung (CvZ)=1 ist erfüllt, wenn im Condition-Code-Register das C-Flag oder das Z-Flag oder beide gesetzt sind. Es ist: R < M.

BLS | $12 | 23 12
LBLS | $1000 | 10 23 10 00

BHI/LBHI (Branch on Higher)
Ein relativer Sprung wird ausgeführt, wenn die Bedingung (ZvC)=0 erfüllt ist, d.h. das Zero Flag und das Carry Flag des Statuswortes müssen beide den Wert "0" haben. Das gilt für: R > M.

BHI | $A1 | 22 A1
LBHI | $10A1 | 10 22 10 A1

BHS/LBHS (Branch on Higher or Same)
Es wird ein relativer Sprung ausgeführt, wenn das Carry Flag im CC-Register den Wert "0" hat. Dieser Befehl ist identisch mit dem Befehl BCC (Branch on Carry Clear). Für M und R gilt nun: R > M.

BHS | $55 | 24 55
LBHS | $4455 | 10 24 44 55

| 1.2 Bedienung des µRechners |  | 1.4 Anleitung zur Lösung der Übungsaufgaben |