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):

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):


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:

BABSFunktion
0 0Normaler Busbetrieb
01 Unterbrechung oder Rücksetzen (RESET)
10 SYNC-Quittung
11 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).

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.

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  #IRQmaskierbarer Interrupt
 FFFA   FFFB  SWI1Software-Interrupt1
 FFF4   FFF5   SWI2Software-Interrupt2
 FFF2   FFF3   SWI3Software-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 Interruptgesetztes Flag
im CC Register
gesperrte
Interrupts
1#NMI E,F,I#IRQ, #FIRQ
2#FIRQ -,F,I#IRQ, #FIRQ
3#IRQE,-,I #IRQ
4 SWI1E,F,I#IRQ, #FIRQ
5SWI2E,-,- ----
6 SWI3E,-,-----

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.NameFunktion Länge
A Accumulator8-bit-Akkumulator 8 bit
BAccumulator 8-bit-Akkumulator 8 bit
DAccumulator (A,B) 16-bit-Akkumulator 16 bit
PCProgram Counter Programmzähler 16 bit
XIndex Register Indexregister mit Auto-Inkr./Dekr., 16 bit
YIndex Register auch als Universalreg. einsetzbar 16 bit
UUser Stack Pointer Stackregister für Benutzer- oder 16 bit
SSystem Stack Pointer Systemstack, PUSH/PULL-Befehle 16 bit
DPDirect Page Register Seiten-Adreßregister 8 bit
CCCondition Code Register Statusregister8 bit

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 #$F086 F0 Lade Akku A mit $F0
LDX #$12348E 12 34 Lade X-Reg. mit $1234
LDY #$ABCD10 8E AB CD Lade Y-Reg. mit $ABCD
SWI13F(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*YX DPBACC
  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

RegisterBinärcode Hex-Code
D00000
X00011
Y00102
U00113
S01004
PC0101 5
A1000 8
B1001 9
CC1010 A
DP1011 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:
DECA4A
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
SWI13F(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
SWI13F(zum Monitor)
Lade Akkumulator A mit dem Wert der Zelle $00EB

1.3/14

2.
LDB #$1AC6 1A(DP auf $1A
TFR B,DP1F 9Bsetzen)
LDA <$EB96 EBOpCode, Kurzadresse
...........   
LDB #0C6 00(Restaurieren des DP-Registers
TFR B,DP1F 9Bfür den Monitor)
SWI13F(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 #$1086 10
TFR A,DP1F 8B bzw. EXG A,DP1E 8B
LDB <$15D6 15 OpCode, Kurzadresse
LDA #086 00
TFR A,DP1F 8B
SWI13F

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
1rrd/i Adressierungsart
d/i=0: direkt, d/i=1: indirekt
b)
5-bit-Offset
b7 b6 b5 b4 b3 b2 b1 b0
0rrn nnnn
nnnnn: 5-bit-Offset im Zweierkomplement
Registerrr
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.
OffsetDirekt X
~
+
#
IndirektX
~
+
#
AssemblerPostbyte (Hex) AssemblerPostbyte(Hex)
1kein Offset ,R1rr0010000 [,R]1rr1010030
25-Bit*n,R 0rrnnnnn10 8-Bit Offset benutzen //
38-Bitn,R 1rr0100011[n,R] 1rr1100041
416-Bitn,R 1rr0100142[n,R] 1rr1100172
5A-Register A,R1rr0011010 [A,R]1rr1011040
6B-Register B,R1rr0010110 [B,R]1rr1010140
7D-Register D,R1rr0101140 [D,R]1rr1101170
8Inc. um1 ,R+1rr0000020 nicht erlaubt //
9Inc. um 2 ,R++1rr0000130 [,R++]1rr1000160
10Dec. um 1 ,-R1rr0001020 nicht erlaubt/ /
11Dec. um 2 ,--R1rr0001130 [,--R]1rr1001160
12PCR 8-Bit n,PCR1rr01100 1)1 1[n,PCR]1rr11100 2) 41
13PCR 16-Bit n,PCR1rr01101 1)5 2[n,PCR]1rr11101 2) 82
14 Extended
Indirekt
----[n] 1rr11111 2)52

*) 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
SWI13F(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
SWI13F(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
SWI13F(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
SWI13F(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,YA6 A5 Opcode, Postbyte
SWI13F(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
SWI13F(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 C1Opcode, Postbyte
SWI13F(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 82Opcode, Postbyte
SWI13F(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
SWI13F(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
SWI13F (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:

EAeffektive Adresse, DPDirect Page Register,
AAkkumulator A,X Indexregister
und die Nummern 1- 5 bezeichnen die folgenden Befehle:

1LDA #$30
2LDA <$30 : EA=256*DP+$30
3LDA 18,X : EA=$AF00+$12
4LDA $8FD6 : EA=$8FD6
5LDA [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
ADCB10,XE9 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#$108B 10
ADDB10,XEB 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$1243F4 12 43
ANDCC#$AA1C 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$123477 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$EED5 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
CLR13124,Y6F 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$AAD1 AA
CMPD13124,S10 A3 E9 33 44
CMPS10,U11 AC 4A
CMPU$123411 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$123473 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.

CWAI3C xxxx
:FF :FIRQ und IRQgesperrt
EF :FIRQ gesperrt
BF :IRQgesperrt
AF :kein Interruptgesperrt

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#$6786 67 BCD-Zahl 67
ADDA #$759B 75BCD-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$AA0A 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$1234F8 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,
EXGA,B1E 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
INC10,X6C 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 50DP*256+$0050
JMP$1234 7E 12 34$1234
JMPA,X 6E 86X+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
JSRA,SAD 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$AAD6 AA
LDD10,XEC 0A
LDS#$123410 CE 12 34
LDU#$11CE 11
LDX$0A9E 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 !)

LEAX1,X 30 01
LEAY,-Y31 A2
LEAS,X32 84
LEAUB,X33 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$1208 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
LSR20,X64 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$AA00 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$1234FA 12 34
ORCC#$111A 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 b5b4 b3b2 b1b0
PC* YX DPB ACC

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

PSHU#$8836 88 (10001000)
PULU#$88 37 88(10001000)
PSHS#$FF34 FF (11111111)
PULS#$FF35 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$1F09 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
ROR10,X66 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,XE7 84
STD$201FFD 20 1F
STS[D,X]10 EF 9B
STU,-XEF 82
STX$A00ABF A0 0A
STY20,X10 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$EBD0 EB
SUBD$1234B3 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 b6b5 b4b3 b2b1 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 !

TFRX,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$1F0D 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$123416 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$123410 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$123417 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$ABCD10 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$556610 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$112210 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$010210 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$300110 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$A0A110 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$123410 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$ABCD10 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$CDEF10 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$101110 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$123410 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$122110 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$778810 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$100010 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$10A110 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$445510 24 44 55

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