- Informatik 4 - RWTH

Werbung
Rechnerstrukturen
Skript zur Vorlesung an der RWTH-Aachen
Lehrstuhl für Informatik IV
Prof. Dr. O. Spaniol
Dr. Mesut Güneş
Ralf Wienzek
2
Inhaltsverzeichnis
1 Grundlegende Konzepte
1.1
Funktionelle Einheiten eines Rechners . . . . . . . . . . . . . . . .
1
1.2
Speicher . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3
1.3
Programmausführung . . . . . . . . . . . . . . . . . . . . . . . . .
4
1.3.1
Von-Neumann-Prinzip . . . . . . . . . . . . . . . . . . . .
4
1.3.2
Alternative Modelle . . . . . . . . . . . . . . . . . . . . .
5
1.3.3
Pipelining . . . . . . . . . . . . . . . . . . . . . . . . . . .
5
1.3.4
Ausführungssteuerung . . . . . . . . . . . . . . . . . . . .
6
Datenübertragung . . . . . . . . . . . . . . . . . . . . . . . . . . .
7
1.4.1
Leitungen . . . . . . . . . . . . . . . . . . . . . . . . . . .
7
1.4.2
Busse . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7
1.4
2
1
Informationsdarstellung
9
2.1
9
Allgemeines zur Darstellung ganzer Zahlen . . . . . . . . . . . . .
2.1.1
2.2
2.3
Stellenwertcodierung . . . . . . . . . . . . . . . . . . . . .
10
Codierungen für ganze Zahlen . . . . . . . . . . . . . . . . . . . .
11
2.2.1
Betrag- und Vorzeichen . . . . . . . . . . . . . . . . . . . .
11
2.2.2
2-Komplement . . . . . . . . . . . . . . . . . . . . . . . .
12
2.2.3
1-Komplement . . . . . . . . . . . . . . . . . . . . . . . .
13
2.2.4
Transformation von negativen Zahlen . . . . . . . . . . . .
14
2.2.5
Addition und Subtraktion . . . . . . . . . . . . . . . . . . .
15
2.2.6
Überlaufproblematik . . . . . . . . . . . . . . . . . . . . .
16
Darstellung rationaler Zahlen . . . . . . . . . . . . . . . . . . . . .
17
2.3.1
Festkommazahlen . . . . . . . . . . . . . . . . . . . . . .
17
2.3.2
Gleitkommazahlen . . . . . . . . . . . . . . . . . . . . . .
18
i
ii
Inhaltsverzeichnis
2.4
2.5
3
Addition und Subtraktion bei Gleitkommazahlen . . . . . .
20
2.3.4
Multiplikation und Division bei Gleitkommazahlen . . . . .
21
Darstellung von Zeichen . . . . . . . . . . . . . . . . . . . . . . .
22
2.4.1
Codierung mit Umschaltsymbolen . . . . . . . . . . . . . .
22
2.4.2
Codierung durch Bitstrings . . . . . . . . . . . . . . . . . .
23
2.4.3
Darstellung von Dezimalziffern . . . . . . . . . . . . . . .
24
Erkennung und Behebung von Bitfehlern . . . . . . . . . . . . . . .
25
2.5.1
26
Hamming-Distanz . . . . . . . . . . . . . . . . . . . . . .
Maschinennahe Programmierung
29
3.1
Darstellung von Befehlen . . . . . . . . . . . . . . . . . . . . . . .
29
3.1.1
Aufbau eines Befehlswortes . . . . . . . . . . . . . . . . .
29
3.1.2
Befehlstypen . . . . . . . . . . . . . . . . . . . . . . . . .
33
3.1.3
Befehlssätze . . . . . . . . . . . . . . . . . . . . . . . . .
34
3.1.4
Verwendung zusätzlicher Register und Registerbefehle . . .
34
Adressierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
35
3.2.1
Direkte Adressierung . . . . . . . . . . . . . . . . . . . . .
35
3.2.2
Indirekte Adressierung durch Basisregister und Relative Distanz . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
35
3.2.3
Indexregister zur indirekten Adressierung . . . . . . . . . .
36
3.2.4
Indexregister mit Adressmodifikation . . . . . . . . . . . .
37
3.2.5
Unterschiedliche Adressmodi . . . . . . . . . . . . . . . .
37
3.2.6
Indirekte Adressierung . . . . . . . . . . . . . . . . . . . .
37
3.2.7
Modifizierung von Befehlen . . . . . . . . . . . . . . . . .
38
Leistungsfähigkeit von Adressiertechniken . . . . . . . . . . . . . .
38
3.3.1
Berechnung durch ein Programm . . . . . . . . . . . . . .
38
3.3.2
Endlichkeit der realen Maschine . . . . . . . . . . . . . . .
39
3.3.3
Beliebig große Funktionswerte sollen berechenbar sein . . .
42
Unterprogramme . . . . . . . . . . . . . . . . . . . . . . . . . . .
42
3.4.1
Einstufige, nichtrekursive Unterprogramme . . . . . . . . .
43
3.4.2
Mehrstufige, nichtrekursive Unterprogramme . . . . . . . .
44
3.4.3
Mehrstufige, eventuell rekursive Unterprogramme . . . . .
44
3.2
3.3
3.4
4
2.3.3
Bausteine und Komponenten von Rechensystemen
47
4.1
47
Schaltfunktionen, Bausteinsysteme und Boolesche Algebra . . . . .
Inhaltsverzeichnis
4.2
4.3
4.4
5
iii
4.1.1
Entwurf und Realisierung von Schaltfunktionen . . . . . . .
49
4.1.2
Atom, Minterm und Maxterm . . . . . . . . . . . . . . . .
54
4.1.3
Boolesche Ausdrücke . . . . . . . . . . . . . . . . . . . . .
56
Normalformen . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
59
4.2.1
Disjunktive Normalform (DNF) . . . . . . . . . . . . . . .
59
4.2.2
Konjunktive Normalform (KNF) . . . . . . . . . . . . . . .
60
4.2.3
Komplementfreie Ringsummenentwicklung (KRE) . . . . .
60
Synthese von Schaltkreisen, Minimierung . . . . . . . . . . . . . .
62
4.3.1
Eingeschränktes Minimierungsproblem . . . . . . . . . . .
63
4.3.2
Quine-McCluskey-Algorithmus . . . . . . . . . . . . . . .
64
4.3.3
Karnaugh-Diagramme . . . . . . . . . . . . . . . . . . . .
70
Schaltwerke und Speicherelemente . . . . . . . . . . . . . . . . . .
71
4.4.1
72
Speicherelemente . . . . . . . . . . . . . . . . . . . . . . .
Die Arithmetisch-Logische Einheit
79
5.1
Addition und Subtraktion . . . . . . . . . . . . . . . . . . . . . . .
80
5.1.1
Halbaddierer . . . . . . . . . . . . . . . . . . . . . . . . .
80
5.1.2
Volladdierer . . . . . . . . . . . . . . . . . . . . . . . . . .
81
5.1.3
Carry-Ripple-Addierer . . . . . . . . . . . . . . . . . . . .
82
5.1.4
Serieller Addierer . . . . . . . . . . . . . . . . . . . . . . .
84
5.1.5
Von-Neumann-Addierer . . . . . . . . . . . . . . . . . . .
86
5.1.6
Erweiterungen des Von-Neumann-Addierers . . . . . . . .
90
5.1.7
Carry-Look-Ahead-Addierer . . . . . . . . . . . . . . . . .
93
5.1.8
Carry-Skip-Addierer . . . . . . . . . . . . . . . . . . . . .
95
5.1.9
Conditional-Sum-Addierer . . . . . . . . . . . . . . . . . .
99
Multiplikation . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
102
5.2.1
Serielle Multiplikation . . . . . . . . . . . . . . . . . . . .
103
5.2.2
Multiplikatorcodierung . . . . . . . . . . . . . . . . . . . .
105
5.2.3
Adder-Tree und Pipelining . . . . . . . . . . . . . . . . . .
108
Division . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
110
5.3.1
Serielle Division . . . . . . . . . . . . . . . . . . . . . . .
110
5.3.2
Iterative Division . . . . . . . . . . . . . . . . . . . . . . .
115
5.3.3
Iterative Berechnung von Quadratwurzeln . . . . . . . . . .
119
Arithmetik bei redundanter Zahlendarstellung . . . . . . . . . . . .
122
5.2
5.3
5.4
iv
Inhaltsverzeichnis
5.4.1
SDNR-Darstellung für die Addition . . . . . . . . . . . . .
122
5.4.2
Gemischtes SDNR-Verfahren . . . . . . . . . . . . . . . .
124
5.4.3
SRT-Verfahren zur seriellen Division . . . . . . . . . . . .
125
Abbildungsverzeichnis
1.1
Komponenten eines Rechners . . . . . . . . . . . . . . . . . . . . .
2
1.2
Pipelining von Befehlen . . . . . . . . . . . . . . . . . . . . . . .
5
1.3
Ausführungssteuerung mit Interruptsignalen . . . . . . . . . . . . .
6
1.4
Zwei-Bus-Architektur . . . . . . . . . . . . . . . . . . . . . . . . .
7
1.5
Unibus-Architektur . . . . . . . . . . . . . . . . . . . . . . . . . .
8
1.6
Pufferung des Buszugangs . . . . . . . . . . . . . . . . . . . . . .
8
2.1
Kodierung einer Gleitkommazahl . . . . . . . . . . . . . . . . . . .
18
3.1
Befehlsstrukturen . . . . . . . . . . . . . . . . . . . . . . . . . . .
31
3.2
Indirekte Adressierung mit Basisregister und relativer Distanz . . .
36
3.3
Algorithmus zur Berechnung von h0 , h1 , . . . . . . . . . . . . . . . .
41
3.4
Aufruf und Beenden von Unterprogrammen . . . . . . . . . . . . .
43
3.5
Einstufiger Unterprogrammaufruf . . . . . . . . . . . . . . . . . .
44
3.6
Mehrstufiger Unterprogrammaufruf . . . . . . . . . . . . . . . . .
44
4.1
Karnaugh-Diagramme . . . . . . . . . . . . . . . . . . . . . . . .
70
4.2
Schaltkreis und Schaltwerk . . . . . . . . . . . . . . . . . . . . . .
72
4.3
Takt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
72
4.4
RS-Flipflop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
73
4.5
Schaltung des RS-Flipflops . . . . . . . . . . . . . . . . . . . . . .
74
4.6
Schaltsymbole für das RS-Flipflop . . . . . . . . . . . . . . . . . .
75
4.7
Earle Latch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
75
4.8
Schaltung des Earle Latch . . . . . . . . . . . . . . . . . . . . . .
76
4.9
Hazards . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
76
4.10 Taktflanke . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
77
v
vi
Abbildungsverzeichnis
5.1
Addition nach Schulmethode . . . . . . . . . . . . . . . . . . . . .
80
5.2
Symbol für einen Halbaddierer . . . . . . . . . . . . . . . . . . . .
80
5.3
Schaltung für den Halbaddierer . . . . . . . . . . . . . . . . . . . .
81
5.4
Schaltung und Schaltsymbol eines Volladdierers . . . . . . . . . . .
82
5.5
Carry-Ripple-Addierwerk . . . . . . . . . . . . . . . . . . . . . . .
83
5.6
Serielles Addierwerk . . . . . . . . . . . . . . . . . . . . . . . . .
84
5.7
Von-Neumann-Addierwerk . . . . . . . . . . . . . . . . . . . . . .
86
5.8
Ablaufsteuerung . . . . . . . . . . . . . . . . . . . . . . . . . . . .
88
5.9
Dioden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
89
5.10 Diodenmatrix . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
90
5.11 Kurznotation des Von-Neumann-Addierers . . . . . . . . . . . . . .
91
5.12 Carry-Save-Addierer . . . . . . . . . . . . . . . . . . . . . . . . .
91
5.13 Lineare Verschaltung von CSAs . . . . . . . . . . . . . . . . . . .
92
5.14 Wallace Tree . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
93
5.15 Carry-Look-Ahead-Addierer für Gruppengröße 4 . . . . . . . . . .
94
5.16 Gruppe eines Carry-Skip-Addierers . . . . . . . . . . . . . . . . .
96
5.17 Schaltung zum Carry-Skip-Addierer zweiter Ordnung . . . . . . . .
98
5.18 Kombination von Carry-Skip und Carry-Look-Ahead . . . . . . . .
99
5.19 Gruppen bei der Conditional-Sum-Addition . . . . . . . . . . . . .
99
5.20 Schema zur seriellen Multiplikation . . . . . . . . . . . . . . . . .
104
5.21 Multiplikation als Addition im Adder-Tree . . . . . . . . . . . . . .
109
5.22 Pipelining durch Adder-Tree . . . . . . . . . . . . . . . . . . . . .
109
5.23 Adder-Tree für Einzelmultiplikation . . . . . . . . . . . . . . . . .
110
5.24 Serielle Multiplikation und Division . . . . . . . . . . . . . . . . .
111
5.25 Table-Look-Up-Methode . . . . . . . . . . . . . . . . . . . . . . .
115
5.26 Newton-Verfahren . . . . . . . . . . . . . . . . . . . . . . . . . . .
116
KAPITEL 1
Grundlegende Konzepte
Wir befassen uns in dieser Vorlesung mit digitalen und programmgesteuerten Rechensystemen. Der Rechner akzeptiert digitale Eingabedaten (Eingangsargumente),
verarbeitet sie mit einem Programm, das in seinem Speicher steht, und produziert digitale Ausgabedaten. Nimmt man vereinfachend an, dass die Eingabedaten im Speicher stehen und die Ergebnisse ebenfalls im Speicher abgelegt werden, dann bewirkt
ein Programm eine Transformation des alten Speicherinhaltes in einen neuen Speicherinhalt.
Rechnersysteme unterscheiden sich grundlegend voneinander bezüglich Größe, Geschwindigkeit, Zahl anschließbarer beziehungsweise bedienbarer Geräte oder Benutzer und ihrer Kosten. Eine mögliche Klassifizierung von Rechnersystemen ist die
Folgende, wobei die Grenzen zwischen den Klassen fließend sind:
• Supercomputer
• Workstation
• Personal Computer
• Prozessrechner
• Personal Digital Assistant (PDA)
• Smartphone
1.1 Funktionelle Einheiten eines Rechners
Ein Rechnersystem besteht aus folgenden Einheiten, die sich aufgrund ihrer Funktion
innerhalb des Systems voneinander unterscheiden.
Die Eing- und die Ausgabeeinheit bilden die Schnittstellen zur Außenwelt. Der Prozessor (Central Processing Unit, CPU) hat Aufgaben der Steuerung und Arithmetik. Er vereinigt demnach die Steuereinheit (Control Unit) und die Recheneinheit
1
2
Kapitel 1. Grundlegende Konzepte
(Arithmetic Logical Unit, ALU). Eine weitere wichtige Einheit ist der Speicher. Auf
ihn wird später eingegangen. Abbildung 1.1 veranschaulicht die Zusammenarbeit der
einzelnen Komponenten.
Es gibt erweiterte Konzepte, bei denen mehrere Rechner zusammenarbeiten, wobei
diese dann durch ein Kommunikationsnetz verbunden sind.
Rechner
Außenwelt
Mensch,
elektr. Gerät,
Leitungen zu
anderen
Rechnern
Eingabe
Datenprozessor
RAM
Ausgabe
Befehlsprozessor
ROM
CPU
Speicher
Steuerinformationen
Daten
Abbildung 1.1: Komponenten eines Rechners
Ein Rechensystem verarbeitet Informationen, die im Speicher gehalten werden. Man
unterscheidet zwei Arten von Informationen. Zum einen Befehle, die Aktivitäten des
Prozessors anstoßen, und auf der anderen Seite Daten, die manipuliert werden. Ein
Programm ist dabei eine Folge von Befehlen. Typische Daten sind zum Beispiel Zahlen und Zeichen, die in geeigneter Codierung im Speicher abgelegt werden. Da sich
ein Programm meist auch im Speicher befindet, sind die Codierungen der Befehle
auch als Daten auffassbar.
Der Prozessor verarbeitet Informationen im einfachsten Fall nach folgendem Ablauf:
1. Befehl (aus dem Speicher) holen
2. Befehl interpretieren
3. Aufgrund der Interpretation des Befehls nötige Operanden holen
4. Befehl (Operation) ausführen
Anschließend wird dieser Ablauf mit dem nächsten Befehl durchgeführt.
Die Bearbeitung erfolgt sequenziell, das heißt, die Befehle werden nacheinander und
jeder für sich zu einem Zeitpunkt ausgeführt.
Es gibt Befehle, deren Aufgabe es ist, nicht den nachfolgenden, sondern einen an
anderer Stelle im Speicher befindlichen Befehl anzustoßen (so genannter Sprungbefehl). Ferner dienen Vergleichsbefehle dazu, Fallunterscheidungen zu bilden, so dass
aufgrund eines Speicherzustandes eine bestimmte Aktion ausgeführt wird.
1.2. Speicher
3
Üblicherweise werden ein Programm (oder auch mehrere) und die dazugehörigen
Daten im Speicher gehalten. Zu diesem Zweck enthält der Speicher eine Menge von
adressierbaren Speicherzellen (Worten).
Zur Unterscheidung zwischen Daten und Befehlen muss man entweder die Speicherzelle markieren (zum Beispiel ein gesondertes Bit des Wortes zur Verfügung stellen
wie: 1 steht für Datum und 0 steht für Befehl) oder den aktuellen CPU-Zustand interpretieren.
Die folgende Abbildung zeigt den Speicher, der in zwei Abschnitte zur Aufnahme
von Programmen und Rechendaten aufgeteilt ist.
Adresse Inhalt
0
..
..
Programmspeicher P
.
.
N1 − 1
0
..
..
.
.
Rechenspeicher R
N2 − 1
Wir nehmen also ohne wesentliche Einschränkung an, dass wir zwei Speicher P und
R haben, die jeweils von Null ab adressiert werden. Den Inhalt der Speicherzellen
kennzeichnen wir im Fall eines
• Befehls mit π(i): aktueller Inhalt von Zelle i in P
• Datums durch ρ( j): aktueller Inhalt der Zelle j in R
1.2 Speicher
Man unterscheidet im Wesentlichen drei Arten von Speicher. Der Hauptspeicher
(Primary Memory, Main Memory) ist direkt adressierbar mit nahezu gleicher Zugriffszeit pro Zelle (typische Werte liegen bei einigen Nanosekunden). Er wird demnach auch als Random Access Memory (RAM) bezeichnet. Einen Hintergrundspeicher (Secondary Memory) verwendet man zur Speicherung relativ selten benötigter Informationen. Er ist langsamer bezüglich der Zugriffszeit. Da er nicht die teuren und schnellen Speicherbausteine verwendet, ist er wesentlich billiger und daher
auch in größerem Umfang verfügbar. Als Beispiel ist Festplattenspeicher zu nennen.
Der Pufferspeicher (Cache Memory) zeichnet sich dadurch aus, dass er besonders
schnell, dafür aber auch teuer ist. Aus diesem Grund ist er relativ klein. Seine besondere Eignung liegt in der Pufferung (vom Prozessor) besonders häufig benutzter
Befehle und Daten.
Neben den Speichertypen gibt es die Register. Es handelt sich dabei um Zellen mit
besonders kurzen Zugriffszeiten. Den Registern werden bestimmte Sonderaufgaben
zugeordnet, wie sie im Folgenden beispielhaft aufgeführt sind. Dabei unterscheiden
wir der Einfachheit halber nicht zwischen Registername und Registerinhalt.
4
Kapitel 1. Grundlegende Konzepte
Das Akkumulatorregister (der Akkumulator, Bezeichnung durch α) dient der kurzfristigen Speicherung von Informationen. Es wird für den Transfer vom und zum
Speicher benutzt. Verwendung findet es zum Beispiel bei der Ausführung arithmetischer Operationen.
Eine typische Befehlsfolge unter Verwendung des Akkumulators ist die folgende:
1
2
3
4
α = ρ(0)
α = α + ρ(1)
α = α + ρ(2)
ρ(0) = α
Dieses Programm sorgt für eine Addition der Inhalte der ersten drei Rechenspeicherzellen. Die Summe wird in die erste Speicherzelle geschrieben.
Das Indexregister (bezeichnet mit γ) wird bei der indizierten Adressierung verwendet, die in Kapitel 3 eingeführt wird.
Nicht zu verwechseln sind das Befehlsregister (Instruction Register, IR) und das
Befehlszählregister (Program Counter, PC) auch mit β bezeichnet). Das Befehlsregister enthält den Befehl, der momentan ausgeführt wird. Dahingegen steht im Befehlszählregister die Adresse des zur Zeit ausgeführten Befehls. Ist die Ausführung
des einen Befehls abgeschlossen und soll der nächste Befehl ausgeführt werden, so
wird der Inhalt des Befehlszählregisters inkrementiert (β = β + 1).
Das Speicheradressregister (Memory Address Register, MAR) enthält die Adresse einer Speicherzelle, während das Speicherdatenregister (Memory Data Register,
MDR) das Datum dieser durch das Speicheradressregister angesprochenen Speicherzelle enthält.
Darüber hinaus gibt es noch eine architekturabhängige Vielzahl von Allzweckregistern, die meist mit R0 , R1 , R2 , . . . bezeichnet werden. Sie werden für unterschiedliche
Zwecke eingesetzt, zum Beispiel für die Durchführung von Rechenoperationen.
1.3 Programmausführung
Es gibt verschiedene Konzepte zur Ausführung von Befehlen und somit zur Manipulation von Daten.
1.3.1
Von-Neumann-Prinzip
Die konventionelle Programmausführung erfolgt nach dem Von-Neumann-Prinzip.
Es wird zu einem Zeitpunkt ein Befehl auf ein Datum angewandt. Man nennt den
zugehörigen Rechner auch SISD-Rechner (Single Instruction Single Data).
Die Ausführung eines Befehls geschieht in vier Schritten:
1. Hole nächsten Befehl in das Befehlsregister (IR).
Die Adresse des Befehls steht im Befehlszählregister β; demzufolge enthält
β zu Beginn der Programmausführung die Startadresse.
1.3. Programmausführung
5
2. Interpretiere den Befehl.
Es wird der Typ des Befehls ermittelt und die Anzahl nötiger Operanden bestimmt.
3. Hole den beziehungsweise die benötigten Operanden.
4. Führe den Befehl aus.
Der Hole-Befehl (Load) beschreibt einen Datentransfer zwischen Speicher und Prozessor. Er hat die Form α = ρ(i) und bedeutet »Lade Datum von Speicherzelle i in den
Akkumulator«. Entsprechend lautet der Befehl für einen Speichere-Befehl (Store)
ρ(k) = α.
1.3.2
Alternative Modelle
Neben dem SISD-Prinzip gibt es folgende andere Typen, die hier nur kurz genannt
werden. Der SIMD-Rechner (Single Instruction Multiple Data) gestattet die Anwendung eines Befehls zu einem Zeitpunkt auf mehrere Daten. Es gibt Rechnertypen, die
hierzu mehrere Prozessoren verwenden, welche zum Beispiel einen gemeinsamen
Speicher nutzen (Shared Memory Model). Ein weiteres Modell stellt der MIMDRechner dar (Multiple Instruction Multiple Data), selten wird der MISD-Rechner
(Multiple Instruction Single Data) verwendet.
1.3.3
Pipelining
Die Befehlsausführung nach dem Von-Neumann-Prinzip in vier Schritten kann beschleunigt werden, wenn man Schritt 1 und 2 des nachfolgenden Befehls mit den
Schritten 3 und 4 des aktuell auszuführenden Befehls kombiniert. Abbildung 1.2
zeigt, dass der Prozessor nach der Interpretation des Befehls i (Schritt 2) zusätzlich zu dessen weiterer Bearbeitung (Schritte 3 und 4) den Befehl (i + 1) holt und
interpretiert.
Zeit
0
1
2
3
4
5
..
.
Befehl 1
Hole Befehl 1
Interpretiere Befehl 1
Operanden holen
Befehl 1 ausführen
Befehl 2
Befehl 3
Hole Befehl 2
Interpretiere Befehl 2
Operanden holen
Befehl 2 ausführen
Hole Befehl 3
Interpretiere Befehl 3
...
Abbildung 1.2: Pipelining von Befehlen
Zu beachten ist allerdings, dass die Ausführung von Befehl i (Schritt 4) unter Umständen erst den Befehl (i+1) festlegen kann. In diesem Fall ist irrtümlich der falsche
6
Kapitel 1. Grundlegende Konzepte
Befehl (i + 1) ausgeführt worden, was zu ungewünschten Folgen führen kann. Der
nun richtige Befehl (i + 1) muss, sofern noch möglich, ausgeführt werden.
1.3.4
Ausführungssteuerung
Neben den Befehlen zum Datentransfer zwischen Prozessor und Speicher werden
auch die Ein-/Ausgabegeräte (Input/Output, I/O) über E/A-Befehle vom Prozessor
angesteuert. Ihre Tätigkeit können solche Endgeräte dann weitgehend unabhängig
vom Prozessor ausführen. Eine wichtige Aufgabe hat der Prozessor bei der Koordination dieser Geräte. Hierzu senden die Endgeräte so genannte Interrupt-Signale,
die den Prozessor in der Ausführung eines anderen Programms unterbrechen. Auf
diese Weise kann von der normalen Befehlsausführung abgewichen werden (siehe
Abbildung 1.3).
Beispiele für derartige Unterbrechungen des Prozessors sind eine Alarmmeldung,
die eine Reaktion innerhalb einer nicht zu überschreitenden Zeitspanne (Deadline)
erfordert, oder eine Fertigmeldung eines langsamen Endgerätes. Der vergleichsweise
schnelle Prozessor bedient normalerweise viele langsame Endgeräte gleichzeitig, er
muss also zwischen gleichzeitig laufenden Programmen umschalten.
Prozessorsteuerprogramm
(Betriebssystem)
Programm 1
Programm 2
Initiiere E/A-Operation 1
für Programm 1
Schalte um zu
Programm 2
E/A 1 meldet „fertig“
durch Interruptsignal
Unterbreche Programm
2 und rette seine
relevanten Informationen
Schalte um zu
Programm 1
Abbildung 1.3: Ausführungssteuerung mit Interruptsignalen
1.4. Datenübertragung
7
1.4 Datenübertragung
1.4.1
Leitungen
Die Kommunikation besteht im Wesentlichen im Transfer von Daten und Steuerinformationen zwischen den funktionellen Einheiten des Rechners, insbesondere
zwischen Prozessor, Speicher und E/A-Geräten. Sie erfolgt über Leitungen, welche
die Einheiten verbinden. Physikalisch gesehen sind Leitungen meist drahtgebunden.
Aber auch andere Möglichkeiten sind gegeben wie etwa Funkstrecken.
Informationstransport auf einer Leitung erfolgt in der Regel sequenziell, d.h. ein Bit
wird nach dem anderen auf die Leitung gebracht und ebenso empfangen. Der parallele Transport bedeutet, dass mehrere Bits gleichzeitig über ein Bündel von Leitungen
gesendet werden. Ein solches Bündel wird auch als Bus bezeichnet.
1.4.2
Busse
Ein Rechnerbus besteht aus einer Menge von Leitungen. Ein Bus ist im Rechner
als öffentliches Transportmedium für mehrere Einheiten aufzufassen, die über diesen
miteinander verknüpft sind. Der Zugriff auf den Bus, also die Busbenutzung, wird
daher auch als Multiple Access (MA) bezeichnet und muss durch Konventionen in
Form von Protokollen geregelt werden.
Busse lassen sich nach den Einheiten charakterisieren, die sie miteinander verbinden.
Ebenso gibt es verschiedene Busarchitekturen, welche die Zuordnung von Bussen an
Einheiten beschreiben. Abbildung 1.4 zeigt eine Architektur mit zwei Bustypen: Der
Datenbus dient der Kommunikation zwischen Prozessoreinheit und dem Speicher.
Ein eigener Rechnerbus sorgt für die Kommunikation des Prozessors mit den E/AGeräten.
Speicher
Datenbus
CPU
E/A-Gerät
E/A-Gerät
Rechnerbus
Abbildung 1.4: Zwei-Bus-Architektur
Einfacher, aber weniger leistungsfähig als diese Zwei-Bus-Architektur ist die Verwendung eines gemeinsamen Busses – so genannter Unibus – für alle Kommunikationsaufgaben zwischen allen Einheiten (siehe Abbildung 1.5).
8
Kapitel 1. Grundlegende Konzepte
Speicher
CPU
E/A-Gerät
E/A-Gerät
Bus für Daten, Befehle, Steuerung...
Abbildung 1.5: Unibus-Architektur
Ein grundlegendes Problem ist die unterschiedliche Geschwindigkeit, mit der die
Komponenten arbeiten, die an einen gemeinsamen Bus angeschlossen sind, zum Beispiel: schnelle CPU und langsames E/A-Gerät. Benutzt eine langsame Einheit den
Bus, so ist er für eventuell längere Zeit für andere Einheiten blockiert. Dies erklärt
auch, warum der Unibus nicht sehr leistungsfähig ist.
Erforderlich sind also Hilfsmittel, welche die Geschwindigkeitsunterschiede glätten,
um weniger Busse verwenden zu können. Ein Lösungsansatz besteht im Einsatz von
Pufferregistern zwischen dem Bus und den angeschlossenen Geräten (siehe Abbildung 1.6). Auf diese Weise kann zum Beispiel eine schnelle CPU viele langsame
Endgeräte wechselweise bedienen. Der Bus ist allerdings nur solange nicht blockiert,
bis der Puffer voll ist.
schnell
Pufferregister
CPU
Puffer E/A
schnell
langsam
CPU
Drucker
Abbildung 1.6: Pufferung des Buszugangs
KAPITEL 2
Informationsdarstellung
In diesem Kapitel werden Darstellungsformen und Codierungen für Zahlen und Zeichen eingeführt. Wir betrachten sowohl gebräuchliche Formen der Darstellung von
ganzen und Gleitkommazahlen als auch Codierungen von Zeichen, denen keine arithmetische Bedeutung zugeordnet ist.
Die Darstellung eines Datums findet meist in einem Speicherwort statt. Es sind auch
Halb- oder Doppelwortdarstellungen gängig. Ein Speicherwort ist somit als Informationseinheit des Rechners zu verstehen. Die Wortlänge ist dabei abhängig vom
Rechner; es handelt sich in der Regel um Potenzen von 2 (16, 32, 64 Bit). Bei Großrechnern findet man auch exotische Werte wie 50- oder 60-Bit-Darstellungen.
2.1 Allgemeines zur Darstellung ganzer Zahlen
Es gilt, eine Darstellung für ganze Zahlen zu finden, so dass sich eine vernünftige
Zuordnung zwischen Codierung und dem Wert der Zahl ergibt. An eine Codierung
werden im Allgemeinen folgende Anforderungen gestellt:
• Zunächst sollten alle positiven und negativen Zahlen eines Intervalls [−x; y]
dargestellt werden können.
• Dabei sollten in etwa gleich viele positive wie negative Zahlen darstellbar sein.
• Die Darstellung sollte – abgesehen von wenigen Ausnahmen – eindeutig sein,
das heißt, zwei unterschiedliche Codeworte beschreiben auch zwei unterschiedliche Werte.
• Eine wichtige Forderung ist die Durchführbarkeit von Rechenoperationen in
der Codierung.
• Eine eher technische Forderung liegt darin, dass die Unterscheidung zwischen
positiver und negativer Zahl möglichst am Anfang des Codeworts getroffen
werden kann. Der Rest wird als Codierung des Stellenwerts aufgefasst.
9
10
Kapitel 2. Informationsdarstellung
2.1.1
Stellenwertcodierung
Die Stellenwertcodierung ist ein gebräuchliches Beispiel für eine vernünftige Zuordnung. Das bekannteste Beispiel ist das Dezimalsystem. Man ordnet einem Codewort (an−1 , . . . , ai , . . . , a0 ) einen Wert zu, der sich ergibt als:
n−1
W(an−1 , . . . , ai , . . . , a0 ) =
∑ ai · d i
i=0
Dabei bezeichnet man d als Basis und ai mit 0 ≤ ai ≤ d − 1 als Stellenwert.
Gebräuchliche Basen sind d = 2, 8, 10, 16. Das Zahlensystem wird entsprechend der
durch die Basis gegebenen Codierung als Binär-, Oktal-, Dezimal- oder Hexadezimal-System bezeichnet. In der folgenden Tabelle sind die vier gebräuchlichsten
Zahlensysteme mit ihren Basen und Alphabeten aufgelistet.
Zahlensystem
Binär
Oktal
Dezimal
Hexadezimal
Basis d
2
8
10
16
Zahlenalphabet
{0, 1}
{0, 1, 2, 3, 4, 5, 6, 7}
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B,C, D, E, F}
Jede Hexadezimalziffer wird in binärer Darstellung durch vier Bits dargestellt. Im
Folgenden betrachten wir jedoch das Binärsystem.
Wir verwenden nun die Stellenwertfunktion W, die eine Unterscheidung zwischen
negativer und positiver Zahl aufgrund des ersten Bits an−1 zulässt:
W : {0, 1}n → Z
W(an−1 , . . . , ai , . . . , a0 ) = (an−1 , Sn−2,0 )
mit
j
S j,i = ∑ ak · 2k
(2.1)
k=i
Man bezeichnet an−1 als Vorzeichenbit und legt fest:
(
+Sn−2,0
W(an−1 , an−2 , . . . , ai , . . . , a0 ) =
−Sn−2,0
falls an−1 = 0
falls an−1 = 1
Diese Codierung erlaubt eine Darstellung von maximal 2n verschiedenen Zahlen. Da
durch das erste Bit aber eine Unterscheidung zwischen positiven und negativen Zahlen getroffen wird und die 0 sowohl als positive als auch negative Zahl interpretiert
wird, ist die betragsgrößte Zahl 2n−1 − 1.
2.2. Codierungen für ganze Zahlen
2.2 Codierungen für ganze Zahlen
In diesem Abschnitt werden drei Codierungen für ganze Zahlen eingeführt. Die Darstellung positiver ganzer Zahlen ist in allen drei Codierungen gleich. Sie unterscheiden sich in der Codierung negativer Zahlen und der 0, der damit zusammenhängenden
Symmetrie und der Größe des Zahlenbereiches. Ferner sind die Rechenoperationen
auf diesen Codierungen unterschiedlich zu handhaben. Als Rechenoperationen werden zunächst nur die Addition und Subtraktion vorgestellt. In Abschnitt 2.3 über
rationale Zahlen werden auch die Multiplikation und Division eingeführt.
Bei der Beschreibung der einzelnen Codierungen wird von einer n-stelligen Binärzahl der Form (bn−1 , . . . , b0 ) ausgegangen und die Summe S j,i aus 2.1 verwendet.
2.2.1
Betrag- und Vorzeichen (B+V-Codierung)
Positive und negative Zahlen
Eine positive Zahl liegt dann vor, wenn bn−1 = 0 ist. Dann ergibt sich der Wert der
Binärzahl als:
WBV (bn−1 , . . . , b0 ) = +Sn−2,0
(2.2)
Bei negativen Zahlen ist das Vorzeichenbit auf 1 gesetzt bn−1 = 1. Der Wert ist dann:
WBV (bn−1 , . . . , b0 ) = −Sn−2,0
Eine negative betragsgleiche Zahl erhält man aus einer positiven, indem man das
Vorzeichenbit kippt, d.h. von 0 auf 1 setzt.
Beispiel: Zahlen in der B+V-Darstellung
Sei n = 6, es ist WBV (001101) = +13 und WBV (101110) = −14.
Sei (b2 , b1 , b0 ) = (011) gegeben mit WBV (011) = +3, dann ergibt sich für (111) der Wert
WBV (111) = −3.
Zahlenbereich und Zahlenverlängerung
Der Zahlenbereich in der B+V-Codierung ist symmetrisch und reicht bei einer nstelligen Binärzahl von −(2n−1 − 1) bis +(2n−1 − 1). Deshalb hat die 0 zwei Darstellungen, nämlich (bn−1 , . . . , b0 ) = (0, . . . , 0) und (bn−1 , . . . , b0 ) = (1, 0, . . . , 0).
Will man eine n-stellige Binärzahl auf m Stellen (m > n) erweitern, so füllt man die
Zahl nach dem Vorzeichenbit an der Stelle (n − 2) mit Nullen auf.
Beispiel: Zahlenverlängerung
Sei n = 5 mit a = (11010) gegeben. Die auf m = 7 Stellen erweiterte Zahl lautet a′ =
(1001010).
11
12
Kapitel 2. Informationsdarstellung
2.2.2
2-Komplement
Der Wert W2K (bn−1 , . . . , b0 ) einer ganzen Zahl in der 2-Komplement-Codierung ergibt sich nach folgender Formel
W2K (bn−1 , . . . , b0 ) = Sn−2,0 − bn−1 · 2n−1
(2.3)
Im Falle, dass bn−1 = 1 ist, wird also durch Subtraktion eine negative Zahl errechnet.
Positive und negative Zahlen
Positive ganze Zahlen haben die gleiche Binärdarstellung im 2-Komplement wie in
der B+V-Codierung.
Eine negative Zahl ergibt sich aus der Formel 2.3, wenn bn−1 = 1 ist. Andererseits erhält man den Wert einer negativen Binärzahl in 2-Komplement-Codierung wie folgt.
Gegeben sei b = (bn−1 , . . . , b0 ) mit W2K (bn−1 , . . . , b0 ) < 0.
1. Man kippe alle Bits von b, es ergibt sich bneu .
2. Eine 1 addieren: bneu = bneu + 1n mit 1n = (0, . . . 0, 1).
3. Zugehörigen Wert in B+V-Codierung bestimmen: U = WBV (bneu ).
4. Der Dezimalwert von b ist dann −U: W2K (b) = −U.
Diese Art der Berechnung versagt nur für (bn−1 , . . . , b0 ) = (1, 0, . . . , 0). Nach der
zweiten Methode ergibt sich der Wert −0. Der Dezimalwert nach Formel 2.3 ist jedoch W2K (1, 0, . . . 0) = −2n−1 .
Beispiel: Zahlen in der 2-Komplement-Darstellung
Sei n = 7 und b = (b6 , . . . , b0 ) = (1010110). Nach Formel 2.3 ergibt sich:
W2K (b6 , . . . , b0 ) = 1 · 24 + 1 · 22 + 1 · 21 − (1 · 26 ) = 22 − 64 = −42
Nach der zweiten Methode ergibt sich:
1. Kippen: bneu = 0101001
2. 1 addieren: bneu = 0101010
3. U = WBV (bneu ) = 1 · 25 + 1 · 23 + 1 · 21 = 42
4. Dezimalwert ist W2K (b) = −U = −42
Zahlenbereich und Zahlenverlängerung
Der Zahlenbereich im 2-Komplement ist asymmetrisch. Er reicht bei einer n-stelligen
Binärzahl von −(2n−1 ) bis +(2n−1 − 1). Die 0 hat also nur eine Darstellung, nämlich
(bn−1 , . . . , b0 ) = (0, . . . , 0)
2.2. Codierungen für ganze Zahlen
13
Will man eine n-stellige Binärzahl auf m Stellen (m > n) erweitern, so füllt man die
Zahl vorne an der Stelle n mit dem Vorzeichenbit auf.
Beispiel: Zahlenverlängerung beim 2-Komplement
Sei n = 5 mit a = (11010) gegeben. Die auf m = 7 Stellen erweiterte Zahl lautet a′ =
(1111010).
2.2.3
1-Komplement
Der Wert W1K (bn−1 , . . . , b0 ) einer ganzen Zahl in der 1-Komplement-Codierung ergibt sich nach folgender Formel:
W1K (bn−1 , . . . , b0 ) = Sn−2,0 − bn−1 · (2n−1 − 1)
(2.4)
Im Falle, dass bn−1 = 1 ist, wird durch Subtraktion eine negative Zahl errechnet.
Positive und negative Zahlen
Positive ganze Zahlen haben die gleiche Binärdarstellung im 1-Komplement wie in
der B+V-Codierung.
Eine negative Zahl ergibt sich aus der Formel 2.4, wenn bn−1 = 1 ist. Andererseits erhält man den Wert einer negativen Binärzahl in 1-Komplement-Codierung wie folgt.
Gegeben sei b = (bn−1 , . . . , b0 ) mit W1K (bn−1 , . . . , b0 ) < 0.
1. Man kippe alle Bits von b, es ergibt sich bneu .
2. Zugehörigen Wert in B+V-Codierung bestimmen: U = WBV (bneu ).
3. Der Dezimalwert von b ist dann −U : W1K (b) = −U.
Beispiel: Darstellung negativer Zahlen in der 1-Komplement-Darstellung
Sei n = 7 und b = (b6 , . . . , b0 ) = (1001010). Nach der Formel 2.4 ergibt sich:
W1K (b6 , . . . , b0 ) = (1 · 23 + 1 · 21 ) − 1 · (26 − 1) = 10 − 63 = −53
Nach der zweiten Methode ergibt sich:
1. Kippen: bneu = 0110101
2. U = WBV (bneu ) = 1 · 25 + 1 · 24 + 1 · 22 + 1 · 20 = 53
3. Dezimalwert ist W1K (b) = −U = −53
Zahlenbereich und Zahlenverlängerung
Die Asymmetrie der 2-Komplement-Codierung ist behoben. Der symmetrische Zahlenbereich reicht nun von −(2n−1 − 1) bis +(2n−1 − 1).
14
Kapitel 2. Informationsdarstellung
Die Zahlenverlängerung im 1-Komplement funktioniert genauso wie im 2-Komplement:
Vorne das Vorzeichenbit beliebig oft anfügen.
2.2.4
Transformation von negativen Zahlen
Wir betrachten in diesem Abschnitt die Transformation von negativen Zahlen von
einer Codierung zur anderen. Dabei sei b = (bn−1 , . . . , b0 ) eine Binärzahl in der B+VCodierung. Wenn das Vorzeichenbit bn−1 = 1 ist, dann haben wir eine negative Zahl.
Transformation zum 1-Komplement
Man kippt alle Bits von b bis auf das Vorzeichenbit. Formal führt man ein ExklusivesOder (Operationszeichen ⊕) zwischen bn−1 und bi für alle Stellen i ∈ {0, . . . , (n−2)}
durch. Die Zahl c = (cn−1 , . . . , c0 ) im 1-Komplement ergibt sich durch
cn−1 = bn−1 und
ci = bn−1 ⊕ bi für alle i ∈ {0, . . . , (n − 2)}
Diese Transformation funktioniert auch in umgekehrter Richtung, also vom 1-Komplement zur B+V-Codierung.
Transformation zum 2-Komplement
Man verfährt zunächst wie bei der Transformation zum 1-Komplement. Nach der
Berechnung von c = (cn−1 , . . . , c0 ) wird in einem weiteren Schritt g = c + 1n mit
1n = (0, . . . 0, 1) berechnet. g ist die Darstellung in der 2-Komplement-Codierung.
Auch diese Transformation funktioniert in umgekehrter Richtung, also vom 2-Komplement zur B+V-Codierung.
Beispiel: Transformation von Zahlen
Sei b = (10110) eine negative Zahl mit WBV (10110) = −6.
Transformation zum 1-Komplement und zurück.
b = 10110 B+V-Codierung
Alle Bits bis auf das Vorzeichenbit kippen.
c = 11001 1-Komplement-Codierung
Alle Bits bis auf das Vorzeichenbit kippen.
b = 10110 B+V-Codierung
Transformation zum 2-Komplement und zurück.
2.2. Codierungen für ganze Zahlen
b=
10110
g=
11001
00001
11010
b=
10101
00001
10110
2.2.5
15
B+V-Codierung
Alle Bits bis auf das Vorzeichenbit kippen.
1n drauf addieren
2-Komplement-Codierung
Alle Bits bis auf das Vorzeichenbit kippen.
1n drauf addieren
B+V-Codierung
Addition und Subtraktion
Zwei Binärzahlen a = (an−1 , . . . , a0 ) und b = (bn−1 , . . . , b0 ) werden addiert, indem
man sie nach Schulmethode komponentenweise addiert.
sn
an−1 an−2 . . . a2 a1 a0
bn−1 bn−2 . . . b2 b1 b0
sn−1 sn−2 . . . s2 s1 s0
Im Falle, dass die Addition an der (n − 1)-ten Stellen einen Übertrag sn liefert, muss
dieser besonders behandelt werden. Die einzelnen Codierungen unterscheiden sich
bei der Behandlung des Übertrages.
B+V-Codierung
Die B+V-Codierung ganzer Zahlen ist ungünstig bezüglich der Addition. Eine Möglichkeit, diese durchzuführen, besteht darin, die Summanden a und b in die Darstellung im 1-Komplement zu transformieren und dort die Addition durchzuführen. Die
Summe s liegt dann im 1-Komplement vor und wird auf gleiche Weise zurück in die
B+V-Codierung überführt.
2-Komplement
Die Addition wird beim 2-Komplement nach Schulmethode durchgeführt, falls ein
Übertrag an der (n − 1)-ten Stelle entsteht, wird dieser Gesamtübertrag ignoriert.
Beispiel: Addition im 2-Komplement
Seien die Summanden a = (1101101) und b = (0011001) gegeben. Die Summe s ergibt
sich dann wie folgt:
1101101
0011001
1|0000110
W2K (a) = −19
W2K (b) = +25
W2K (0000110) = +6
Der Übertrag wird ignoriert!
16
Kapitel 2. Informationsdarstellung
Die Subtraktion kann auf die Addition zurückgeführt werden, indem man a − b als
a + (−b) auffasst. Also muss b in eine negative Zahl umgeformt werden. Anschließend verfährt man man wie bei Addition beschrieben.
1-Komplement
Die Addition wird auch hier nach Schulmethode durchgeführt, falls ein Übertrag an
der (n − 1)-ten Stelle entsteht, wird ein so genannter End-Around-Carry durchgeführt. Die herausfallende Stelle sn = 1 wird gestrichen, dann allerdings auf die bisherige Summe s addiert s = s + 1n mit 1n = (0, . . . , 0, 1). Wenn im 1-Komplement ein
Gesamtübertrag sn = 1 entsteht, dann gilt, dass dieser sowohl den Wert sn · 2n als
auch den Wert sn · 20 = sn · 1 hat, weil man modulo (2n − 1) rechnet, denn
sn · 2n = sn · (2n − 1) + sn = sn
mod (2n − 1) = sn · 20
mod (2n − 1)
Beispiel: Addition im 1-Komplement
Seien die Summanden a = (1101101) und b = (0011001) gegeben. Die Summe s ergibt
sich dann wie folgt:
1101101
0011001
1|0000110
0000001
0000111
W1K (a) = −18
W1K (b) = +25
W1K (0000110) = +6 mit s = (0000110)
Da Übertrag 1n drauf addieren
W1K (0000111) = 7.
Die Subtraktion kann auch hier wieder auf die Addition einer negativen Zahl zurückgeführt werden.
2.2.6
Überlaufproblematik
Wie die vorangehenden Abschnitte und das folgende Beispiel zeigen, kann es bei der
Addition zu einem Überlauf kommen.
Beispiel: Überlaufproblematik
Die Summe von a = (01010) und b = (01100) ist s = (10110). Im 2-Komplement ist der
Dezimalwert W2K (s) = −10. Das korrekte Ergebnis lautet aber: W2K (a) + W2K (b) = +22.
Zwischen beiden Ergebnissen liegt eine Differenz von 32 = 2n = 25 . Dies lässt sich damit
begründen, dass im 2-Komplement mod 2n gerechnet wird. Das Ergebnis W2K (s) = −10
ist also bis auf Vielfache von 2n richtig.
Die Zahlenverlängerung stellt eine mögliche Abhilfe gegen Überlauf. Bei der 2Komplement- und 1-Komplement-Darstellung verdoppelt man das Vorzeichenbit.
Jeder Summand beginnt dann mit zwei gleichen Bits. Sind die ersten beiden Bits der
Summe verschieden, ist das Ergebnis sicherheitshalber zu prüfen.
2.3. Darstellung rationaler Zahlen
17
Beispiel: Überlaufabhilfe
Verlängere a = (01010) zu a′ = (001010) und b = (01100) zu b′ = (001100). Die Summe
ist dann s = (010110). Eine Überprüfung ergibt, dass das Ergebnis korrekt ist.
Der Nachteil dieser Vorgehensweise liegt in einer höheren Redundanz; man verschenkt ein Bit und kann somit nur halb so viele Zahlen darstellen, wie die Bitwortlänge erlaubt. Vorteilhaft ist die Einfachheit dieser Methode.
Ein Kriterium für die Unmöglichkeit eines Überlaufs ist ein Vergleich der Vorzeichen beider Summanden: Ein Überlauf ist unmöglich, wenn die Vorzeichen unterschiedlich sind, oder formal: Sind a = (an−1 , . . . , a0 ) und b = (bn−1 , . . . , b0 ) die zwei
Summanden, dann ist ein Überlauf genau dann unmöglich, wenn an−1 6= bn−1 . Anschaulich lässt sich dies dadurch begründen, dass die Summe einer negativen und
einer positiven Zahl nicht den Zahlenbereich überschreiten wird.
2.3 Darstellung rationaler Zahlen
Die obigen Abschnitte haben die Darstellung von ganzen Zahlen eingeführt. Die
zugehörigen Rechenoperationen sind die Addition und Subtraktion, wobei letztere
sich auf die Addition zurückführen lässt. Will man nun Zahlen dividieren, so reichen
ganze Zahlen nicht aus. In diesem Abschnitt werden Darstellungsformen rationaler
Zahlen eingeführt.
2.3.1
Festkommazahlen
Es gibt zwei Arten der Festkommadarstellung.
(1) Zu einer Binärzahl b = (bn−1 , . . . , b0 , b−1 , . . . , b−m ) stellt man sich ein Komma
zwischen b0 und b−1 vor. Der Wert ergibt sich nach folgender Formel
n−1
WFK (bn−1 , . . . , b0 , b−1 , . . . , b−m ) =
∑
i=−m
bi · d i
(2.5)
Ganze Zahlen haben in dieser Darstellung das gedachte Komma ganz rechts, das
heißt, nach der Stelle b−m .
(2) Eine andere Möglichkeit besteht darin, den Zahlenbereich auf ein offenes Intervall (−1, +1) einzuschränken. Die Binärzahl hat die Form
b = (b0 , b1 , . . . , bn )
wobei b0 das Vorzeichenbit ist und der Wert von b sich nach folgender Formel
berechnet
(
+ ∑ni=1 21i falls b0 = 0
(2.6)
WFK (b) =
− ∑ni=1 21i falls b0 = 1
18
Kapitel 2. Informationsdarstellung
Die Werte −1 und 1 sind auf diese Weise nicht darstellbar, denn die größte darstellbare Zahl ist 1 − 21n .
Beispiel: Festkommazahlen bei einem offenen Intervall
Sei n = 4 und b = (b0 , b1 , b2 , b3 , b4 ). Die kleinste darstellbare Zahl ist WFK (00001) =
1
15
16 und die größte darstellbare Zahl ist WFK (01111) = 16 .
2.3.2
Gleitkommazahlen
Abbildung 2.1 zeigt die Darstellung einer Gleitkommazahl. Der Darstellung einer
rationalen Zahl durch Mantisse a und Exponent e liegt der folgende Satz für reelle
Zahlen zugrunde.
Zahlenwert
Mantisse
Exponent
a
gedachtes Komma
(Mantisse)
e
gedachtes Komma
(Exponent)
Abbildung 2.1: Kodierung einer Gleitkommazahl
Satz: Darstellung von Gleitkommazahlen
1. Jede Zahl z ist darstellbar in der Form
z = a · de
mit der Mantisse a, dem Exponenten e und der Basis der Zahlendarstellung d.
2. Eine Zahl z 6= 0 ist eindeutig darstellbar als
z = a · de
wobei d1 ≤ |a| < 1. Diese Darstellung heißt dann normalisierte Darstellung mit
Mantisse a und Exponent e.
2.3. Darstellung rationaler Zahlen
Beispiel: Gleitkommazahlen
Es soll die Dezimalzahl 5 in die normalisierte Darstellung zur Basis 2 gebracht werden
5
=
=
=
=
=
5 · 20
2, 5 · 21
1, 25 · 22
0, 625 · 23
0, 3125 · 24
(1.01000 | 0010)
(0.10100 | 0011) normalisierte Darstellung
(0.01010 | 0100) . . .
Somit hat die Dezimalzahl 5 die normalisierte Darstellung:
5 = (2−1 + 2−3 ) · 23
mit Mantisse a = (0.10100) und Exponent e = (0011) zur Basis Basis 2, denn
1
2 ≤| 0, 625 |< 1.
Dieses Beispiel legt die Basis 2 zugrunde. Es sind aber auch andere Basen möglich,
wie zum Beispiel d = 16 (hexadezimal).
Für d = 2 erhält man folgende größte, kleinste und betragskleinste Zahl, wenn man
den Exponenten im 2-Komplement fünfstellig und die Mantisse siebzehnstellig darstellt:
Exponent:
größter
01111
kleinster 10000
W2K (01111) = +15
W2K (10000) = −16
Seien für α · 2x , α ∈ [−1; +1) und x ∈ [−16; +15].
Binäre Darstellung:
größte Zahl
kleinste Zahl
betragskleinste Zahl
(1 − 2116 ) · 215
−1 · 215
1 · 2−16
Die Zahlen liegen mit zunehmender Entfernung von Null weiter auseinander, wohingegen sie um die Null extrem dicht liegen, vorausgesetzt, der Zahlenbereich ist symmetrisch gehalten. Wegen der Binärinterpretation des Exponenten lässt sich dieser
dichte Dezimalzahlenbereich verschieben. Denkt man sich zum Beispiel den Exponenten um jeweils 8 größer, also x ∈ [−8; +23], so ist der dichte Bereich ins Positive
verschoben.
Die Mantissenlänge erweitert nicht den Zahlenbereich, sondern sie erhöht die Genauigkeit der Darstellung. Trotzdem sind irrationale Zahlen immer nur ungenau darstellbar.
Das IEEE-754-Format
Das IEEE-754 legt ein Format für die Darstellung von Gleitkommazahlen fest, das
häufig benutzt wird. Es gibt eine Version mit 32 Bit und eine mit 64 Bit. Im Folgenden
wird die Version mit 32 Bit beschrieben.
19
20
Kapitel 2. Informationsdarstellung
1
2
3
0 1234567890123456789012345678901
VZ Exponent e
Mantisse a
Das erste Bit ist ein Vorzeichenbit, wobei 0 eine positive und 1 eine negative Zahl bedeutet. Die folgenden acht Bits bilden den Exponenten e. Die Basis des Exponenten
ist 2. Der Exponent wird in der Excess-127-Darstellung gespeichert. In dieser Darstellung muss vom Exponenten 127 subtrahiert werden, um den eigentlichen Wert
des Exponenten zu erhalten. Die letzten 23 Bits bilden die Mantisse a. Die Mantisse
ist auf die Darstellung 1, . . . normalisiert, wobei die 1 vor dem Komma steht. Die 23
Bits nehmen die 1 nicht auf, sondern nur die Zahlen nach dem Komma!
Definition: Gleitkommazahl im IEEE-754-Format
Eine Gleitkommazahl im IEEE-754-Format repräsentiert die Zahl n mit
n = V Z 1, a · 2e−127
Beispiel: Gleitkommazahl im IEEE-754-Format
Die Zahl n = −0, 75 wird dargestellt als
1 01111110
|{z}
| {z } 10000000000000000000000
|
{z
}
− 126−127=−1
2.3.3
(1,5)10
Addition und Subtraktion bei Gleitkommazahlen
Bei der Addition zweier Zahlen z1 = a1 · d e1 und z2 = a2 · d e2 ist zu beachten, dass die
Exponenten gleich sind. Man geht wie folgt vor:
1. Exponenten anpassen (den kleineren an den größeren)
2. Operation (gemäß der vorangehenden Abschnitte) ausführen
3. Postnormalisieren (Summendarstellung normalisieren)
Auf diese Weise kann es zu einem Genauigkeitsverlust und einer Teilauslöschung bei
begrenzter Stellenanzahl kommen.
Beispiel: Addition und Subtraktion bei normalisierten Gleitkommazahlen
1) Seien z1 = (0, 1101) · 24 und z2 = (0, 1011) · 22 im 2-Komplement gegeben.
(a) Exponentenanpassung
z2 = (0, 0010)11 · 24 wobei die herausfallenden Einsen auf die letzte Stelle gerundet werden z2 = (0, 0011)
(b) Addition
s = (0, 1101) · 24 + (0, 0011) · 24 = (1, 0000) · 24
2.3. Darstellung rationaler Zahlen
21
(c) Postnormalisierung
s = (0, 1000) · 25 , da |W2K (1, 0000)| = 1
Der sich ergebende Dezimalwert ist ungenau WGK (0, 1000) · 25 = 0, 5 · 25 = 16
Der korrekte Wert ist
WGK ((0, 1101) · 24 ) + WGK ((0, 1011) · 22 ) =
1
1 1
1
1 1
+ +
· 24 +
+ +
· 22 = 13 + 2, 75
2 4 16
2 8 16
= 15,75
2) Die Zahl z2 = 0, 9986 · 1039 soll von z1 = 0, 1002 · 1040 subtrahiert werden.
Exakt ergibt sich (1, 002 − 0, 9986) · 1039 = 0, 0034 · 1039 = 0,34 · 1037 .
(a) Anpassung von z2 an den größeren Exponenten
z2 wird zu 0, 09986 · 1040 , aufgrund der begrenzten Stellenanzahl muss die Zahl
gerundet werden z2 = 0, 0999 · 1040
(b) Subtraktion
0, 1002 · 1040 − 0, 0999 · 1040 = 0, 0003 · 1040
(c) Postnormalisierung
0,3000 · 1037
Im Vergleich zum exakten Wert liegt ein großer Fehler vor.
Im Extremfall wird die Mantisse durch Rundungsfehler zu Null und ist nicht mehr
postnormalisierbar. Gleichzeitig kann der Exponent groß bleiben. In diesem Fall
spricht man von einer so genannten Dirty Zero, da die Zahl dann Null ist, obwohl
sich der echte Wert von Null unterscheidet.
2.3.4
Multiplikation und Division bei Gleitkommazahlen
Für die Multiplikation beziehungsweise Division eignet sich die Darstellung mit
Mantisse und Exponent besser. Hier muss keine Exponentenanpassung stattfinden.
Man geht wie folgt vor:
1. Mantissen multiplizieren beziehungsweise dividieren
2. Exponenten addieren beziehungsweise subtrahieren
3. Postnormalisierung wie oben. Hierzu reicht maximal ein Linksshift bei der
Multiplikation beziehungsweise ein Rechtsshift bei der Division aus.
(a1 · d e1 ) · (a2 · d e2 ) = (a1 · a2 ) · d e1 +e2
a1 · d e1
a2 · d e2
=
a1 e1 −e2
·d
a2
1
≤| a1 · a2 |< 1
d2
a1
mit |
|< d
a2
mit
22
Kapitel 2. Informationsdarstellung
Beispiel: Division von Gleitkommazahlen
−0, 9 · 105
= −1, 2 · 10−3 = −0, 12 · 10−2
0, 75 · 108
Der letzte Schritt entsteht durch Postnormalisierung, indem die Mantisse nach rechts geshiftet und der Exponent korrigiert wird.
2.4 Darstellung von Zeichen
In diesem Abschnitt werden Darstellungsformen von Zeichen eingeführt. Es werden
hier keine Forderungen an die Interpretierbarkeit für Rechenoperationen dieser Zeichen gestellt.
Zeichen sind zum Beispiel Buchstaben, Ziffern, Sondersymbole und Steuerzeichen.
Zeichen werden als Folge von Bits (Bitstring) codiert. Ein Wort (Speicherelement)
enthält meist mehrere Zeichen in codierter Form.
Es gibt zwei grundsätzlich unterschiedliche Codierungsarten, die in den folgenden
Abschnitten vorgestellt werden. Die zugrundeliegende Frage ist hierbei: Wie viele
Bits benötigt man, um ein Zeichen eindeutig darzustellen?
2.4.1
Codierung mit Umschaltsymbolen
Bei dieser Codierung gibt es keine eindeutige Zuordnung zwischen Zeichen und
dem codierenden Bitstring. Man verwendet kurze Bitstrings und kann hiermit wenige Zeichen codieren. Um weitere Zeichen darstellen zu können, fasst man diese als
eine weitere Gruppe von Zeichen auf. Ferner verwendet man Umschaltsymbole, die
anzeigen, welcher Gruppe die Zeichen angehören, die die nächsten Bits des Bitstrings
codieren.
Darzustellen seien die 26 Buchstaben des Alphabets (in Form von Großbuchstaben)
und die zehn Ziffern sowie weitere Sonderzeichen. Will man jedes Zeichen durch
fünf Bits codieren, so kann man 25 = 32 verschiedene Zeichen codieren. Dies reicht
offenbar nicht aus, um der Anforderung gerecht zu werden.
Nach der obigen Methode führe man zwei Umschaltsymbole (11111) und (11010)
ein, die anzeigen, dass von jetzt ab nur Buchstaben beziehungsweise nur Ziffern oder
Sonderzeichen im Bitstring folgen. Trifft man also auf ein Umschaltsymbol, so werden die im Bitstring folgenden 5-Bit-Folgen entsprechend dem vorangehenden Umschaltsymbol interpretiert. Diese Codierung erlaubt die Darstellung von 30 Buchstaben sowie 30 Ziffern und Sonderzeichen, wenn man die beiden Umschaltsymbole
berücksichtigt.
Eine Erweiterung wäre die Unterscheidung zwischen Groß- und Kleinschreibung.
Hierzu müssten zwei weitere Umschaltsymbole eingeführt werden: Umschalten Großnach Kleinschreibung und Klein- nach Großschreibung bei Buchstaben. Günstiger ist
in diesem Fall die Einführung von insgesamt drei Umschaltsymbolen für Großbuch-
2.4. Darstellung von Zeichen
23
staben, Kleinbuchstaben und Sonderzeichen bzw. Ziffern.
Zu beachten ist bei dieser Codierung, dass ohne Kenntnis des im Bitstring zuletzt vorgekommenen Umschaltsymbols einer Bitfolge kein eindeutiges Zeichen zugeordnet
werden kann.
Dem Vorteil der Darstellbarkeit vieler Zeichen als kurze Bitfolgen steht die Verlängerung des Bitstrings durch die eingestreuten Umschaltsymbole gegenüber. Zudem
verkleinern viele Umschaltsymbole die Gruppen der tatsächlich zu codierenden Zeichen.
Eine Aufgabe der Informationstheorie ist die Darstellung einer gegebenen Informationsmenge mit möglichst wenigen Bits. Eine Idee liegt darin, häufig vorkommende
Zeichen oder Zeichenkombinationen wie zum Beispiel e oder en mit kurzen Bitfolgen zu codieren, für seltene Zeichen wie q verwendet man längere Folgen.
Die Huffman-Codierung basiert auf der relativen Häufigkeit des Gebrauchs von Zeichen. Die Häufigkeit deutscher Buchstaben ergibt abnehmend das folgende Kunstwort:
ENRISTUDA
2.4.2
Codierung durch Bitstrings
Bei dieser Codierung ordnet man jeder n-stelligen Bitfolge genau ein Zeichen zu.
Somit sind 2n verschiedene Zeichen codierbar.
Beispiel: Codierung durch Bitstrings
Die Darstellung der 26 Großbuchstaben, 26 Kleinbuchstaben und 10 Ziffern ist mit sechs
Bits möglich.
Standardzeichensätze verwenden sieben beziehungsweise acht Bits (ein Byte) pro
Zeichen. Zu nennen ist der ASCII-Code (American Standard Code for Information
Interchange), welcher sieben Bits verwendet. Der EBCDIC-Code (Extended Binary
Coded Decimal Interchange Code) verwendet acht Bits. In Tabellen lassen sich diese
Codierungen nachschlagen.
Die Darstellung von ASCII-Zeichen auf Bytebasis (Erweiterung auf 8 Bits) ermöglicht die Einrichtung einer Übertragungskontrolle. In der 8-stelligen Bitfolge (b7 , . . . , b0 )
codieren die Bits b6 , . . . , b0 das Zeichen, während das so genannte Parity-Bit b7 die
Anzahl der Einsen auf eine gerade Zahl (b0 + . . . + b7 ) mod 2 = 0 ergänzt. Für die
Folge (b6 , . . . , b0 ) = (001101) ist b7 = 1. Ein Bitfehler ist definiert als Kippen eines
Bits. Ein solcher Fehler ist dadurch erkennbar, dass die Summe der bi mod 2 gleich
eins ist. Somit sind Doppelfehler, das heißt Kippen von zwei Bits einer Bitfolge, nicht
erkennbar. Erkennbar sind: 1-Bit-, 3-Bit-,. . . (2k + 1)-Bit-Übertragungsfehler.
24
Kapitel 2. Informationsdarstellung
2.4.3
Darstellung von Dezimalziffern
Zur Darstellung der zehn Ziffern 0, 1, . . . , 9 benötigt man mindestens vier Bits, da mit
drei Bits nur 23 = 8 Zeichen codierbar sind.
BCD-Code
Die Ziffern werden wie folgt im BCD-Code (Binary Coded Decimal) dargestellt: 0
durch 0000, 1 durch 0001, . . . und 9 durch 1001, wobei sechs Redundanzen 1010, . . .,
1111 auftreten.
In ASCII und EBCDIC sind die Ziffern so dargestellt, dass sie bezüglich der Bits
b3 b2 b1 b0 gerade den BCD-Code haben. Bei aufeinanderfolgenden Dezimalziffern ist
eine Unterdrückung von b7 b6 b5 b4 möglich, womit eine dichtere Packung erreicht
werden kann. Überprüfen Sie das ;-)
3-Excess-Code
Der redundante Bereich wird hier auf die Bitfolgen (0000), (0001) und (0010) sowie
auf (1101), (1110) und (1111) verteilt. Eine Dezimalzahl i wird hier also im BCDCode als Dezimalzahl (3 + i) dargestellt.
0000
0001
0010
0011 codiert die 0
0100 codiert die 1
0101 codiert die 2
..
..
.
.
1100 codiert die 9
1101
1110
1111
redundant
redundant
Ein Vorzug dieser Darstellung ist die Möglichkeit, eine Ziffer a in die komplementäre
Ziffer b durch einfaches Kippen der Bits zu überführen, wobei a komplementär zu b
ist, wenn a + b = 9.
Gray-Code
Der Gray-Code ist formal folgendermaßen definiert:
Eine Abbildung aller Dezimalzahlen i mit 0 ≤ i ≤ 2n − 1 für n ≥ 1 durch Bitfolgen
W n (i) der Länge n sei durch Induktion über n wie folgt erklärt:
1. W 1 (0) = 0 und W 1 (1) = 1
2.5. Erkennung und Behebung von Bitfehlern
(
0W n (i)
2. W n+1 (i) =
1W n (2n+1 − 1 − i)
25
falls 0 ≤ i ≤ 2n − 1
falls 2n ≤ i ≤ 2n+1 − 1
Anschaulich konstruiert man eine Folge von Gray-Code-Ziffern, indem man einen
Block von untereinander stehenden Ziffern nach unten spiegelt und vor die Binärzahlen des oberhalb der Spiegelachse befindlichen Blocks 0 und unterhalb der Spiegelachse 1 schreibt:
Beispiel: Gray-Code
Für n = 2 Bits lange Worte W 2 ergibt sich:
0
0
1
1
0
1
1
0
0
1
2
3
00
01
11
10
10
11
01
00
0
1
2
3
4
5
6
7
Für n = 3 Bits lange Worte W 3 erhält man:
0
0
0
0
1
1
1
1
Das Charakteristikum dieser Codierung besteht darin, dass sich beim Übergang von
der Dezimalzahl i nach (i + 1) die zugehörigen Binärzahlen im Gray-Code an genau
einer Stelle unterscheiden.
2.5 Erkennung und Behebung von Bitfehlern
Die Behandlung von Bitfehlern spielt insbesondere im Bereich der Datenkommunikation eine große Rolle, da die Übertragung von Bits häufig durch äußere Einflüsse
gestört wird. Daher hat man Codes eingeführt, durch die man in der Lage ist, auftretende Bitfehler
• zu erkennen
• zu erkennen und zu beheben
Bei einer entsprechenden Codierung verwendet man aus der Menge aller möglichen
(binären) Worten der Länge n nur Folgen mit speziellen Eigenschaften, also eine
Teilmenge der möglichen Codeworte.
Ein einfaches Beispiel für einen fehlererkennenden und behebenden Code ist das
Hinzufügen von Paritätsbits. Diese zusätzlichen Bits werden gerade so gewählt, dass
26
Kapitel 2. Informationsdarstellung
sie sich mit der Gruppe der Bits, auf die sie sich jeweils beziehen, derart ergänzen,
dass sich eine gerade Anzahl von Einsen pro Gruppe ergibt. Analog zu dieser geraden Parität kann man natürlich auch ungerade Parität vereinbaren. Man unterscheidet
Längsparität und Querparität, je nachdem, ob es sich bei der Gruppe um eine aufeinanderfolgende Bitreihe handelt oder aber um alle i-ten Positionen innerhalb einer
größeren Anzahl von Bitreihen. Gemeinsam angewendet bieten Längs- und Querparität ein Mittel, einzelne Bitfehler zu lokalisieren und zu korrigieren. Bis zu drei
Bitfehler werden sicher erkannt. Es kann allerdings in pathologischen Sonderfällen
und einer darüber hinausgehenden Häufung von Fehlern dazu kommen, dass diese
nicht erkannt werden.
Beispiel: Fehlerekennung durch Paritätsbits
10111001 1
00101000 0
10010001 1
Querparität
Längsparität
Wird nun aus der fettgedruckten Eins aufgrund eines Übertragungsfehlers eine Null, so
kann dieser Fehler anhand der zugehörigen Längs- und Querparitätsbits erkannt und behoben werden.
Kippen die fettgedruckten Bits des folgenden Beispiels, so wird dies nicht erkannt.
10111001 1
00101000 0
10010001 1
Querparität
2.5.1
Längsparität
Hamming-Distanz
Die Hamming-Distanz beschreibt ein Abstandsmaß zwischen zwei binären Worten,
das durch die Anzahl der Stellen bestimmt ist, an denen sich die Worte unterscheiden.
Seien a = (an−1 , . . . , a0 ) und b = (bn−1 , . . . , b0 ) binäre Worte der Länge n. Dann ist
n−1
d(a, b) = d((an−1 , . . . , a0 ), (bn−1 , . . . , b0 )) =
∑ | ai − bi |
i=0
die Hamming-Distanz. Je größer d(a, b) ist, desto mehr Störungen sind notwendig,
um a in b zu verwandeln.
Die Hamming-Distanz eines Codes ist definiert als
HD = min(d(a, b))
wobei a und b zulässige Codeworte und a 6= b.
Bei der Paritätsbitcodierung gilt also HD = 2. Im Extremfall sind die zulässigen Codewörter {(0, . . . , 0); (1, . . . , 1)}, somit gilt hier HD = n, wenn n die Länge der Wörter
beschreibt.
2.5. Erkennung und Behebung von Bitfehlern
Wenn ein Code eine Hammingdistanz von 2t + 1 hat, dann gibt es um jedes Codewort
einen Einzugsbereich der Größe t. Die Wörter innerhalb der t-Kugel entsprechen dabei Störungen des Codeworts von maximal t Bits. Geht man davon aus, dass Störungen weniger wahrscheinlich sind als korrekte Übertragungen, so kann man eine
empfangene Folge dem nächstliegenden Codewort zuordnen (Maximum Likelihood
Decision). Damit hat man die Möglichkeit, bis zu t Bitfehler zu korrigieren. Treten
jedoch mehr als t Bitfehler auf, so wird die Entscheidung fehlerhaft.
Bei Codes der Hamming-Distanz 2t sind bis zu t − 1 Bitfehler erkennbar und korrigierbar. t Bitfehler sind erkennbar, aber nicht mehr korrigierbar. Das einfachste Beispiel hierfür ist wieder die Paritätsbitcodierung mit t = 1.
Beispiel: Fehlererkennung/-korrektur
Es werde der folgende Code definiert:
Zeichen Codierung
A
00000000
11000011
E
00000111
R
S
11100000
00111010
T
11111111
U
Dann ist die Hamming-Distanz des Codes
3. Somit gilt hier t = 1, es können also 2Bit-Fehler erkannt und 1-Bit-Fehler korrigiert
werden.
27
28
Kapitel 2. Informationsdarstellung
KAPITEL 3
Maschinennahe Programmierung
In diesem Kapitel wird die maschinennahe Programmierung vorgestellt. Wir betrachten die Darstellung von Befehlen und verschiedene Arten der Speicheradressierung.
Schließlich wird erklärt, was es heißt, Programme und Unterprogramme auszuführen.
3.1 Darstellung von Befehlen
Die Speicherung eines Befehls findet meist in einem Wort statt, manchmal auch in
einem Halbwort oder Doppelwort. Die Interpretation einer Bitfolge setzt in einem
Speicherwort eine Strukturierung voraus, die den gewünschten Befehl identifiziert.
3.1.1
Aufbau eines Befehlswortes
Der Aufbau eines Befehlswortes ist im Allgemeinen folgendermaßen:
Format
Opcode
Adresse 1
...
Adresse k
Format
Das Format legt einerseits die Struktur der Adresscodierung fest; es gibt an, an welcher Binärstelle die Adressen beginnen und wie lang sie sind. Andererseits legt es
Regeln zur Befehlsausführung fest, das heißt, die Zahl der Operanden, Vorrangregelungen oder etwa implizite Operanden wie zum Beispiel den Akkumulator oder
Stack. Oft ist das Format implizit durch den Opcode gegeben.
Opcode
Der Opcode definiert die auszuführende Operation. Aufgrund seines Codes kann zum
Beispiel ein Holebefehl (Code sei 001011) von einem Additionsbefehl (011011) un29
30
Kapitel 3. Maschinennahe Programmierung
terschieden werden.
Man unterscheidet Operationen nach ihrer Stelligkeit, das heißt, anhand der zu ihrer
Ausführung benötigten Operanden.
Beispiel: Opcodes
Nullstellige Operation
Einstellige Operation
Zweistellige Operation
Mehrstellige Operation
HALT (Stop der Programmausführung)
a = −b
a = b op c
Vektoroperation
Adresstypen
Man unterscheidet zwei Typen von Adressen:
1) Operandenadressen geben die Quell- und Zieladressen der Operanden an. Dabei
kann die Adresse zum Beispiel eine Konstante sein.
Beispiel: Adressen
a = b+c
b und c sind Quelladressen und a ist eine Zieladresse.
2) Die Folgebefehlsadresse zeigt an, an welcher Adresse sich die nach diesem Befehl
auszuführende Instruktion befindet.
Die Quell- und Zieladressen können fehlen, wenn sich die auszuführende Operation
auf spezielle Register oder auf den Stack bezieht. Dies wird aus dem Opcode ersichtlich. Die Folgebefehlsadresse fehlt, wenn von der sequenziellen Befehlsausführung
nicht abgewichen wird. Anhand der Operanden-Zahl lassen sich Befehlsstrukturen
unterscheiden (siehe Abbildung 3.1). Die Bezeichnung (x + y)-Befehl bedeutet, dass
der Befehl x Operandenadressen (ohne Register) und y Folgebefehlsadressen verwendet.
Beispiel: (1 + 0)-Befehle
α = ρ(i)
α = α + ρ( j)
ρ(k) = α
Opcode1 , Operandi
Opcode2 , Operand j
Opcode3 , Operandk
Dabei spricht man von Mnemonischer-Darstellung (Assemblerbefehl) und dem Quellcode, bzw. von Binärdarstellung (Objektform) und Objektcode. Der Unterschied
zwischen Quellcode und Objektcode liegt unter anderem in der besseren Lesbarkeit
der Programme im Quellcode, während die Darstellung im Objektcode maschinennäher ist.
Ein Assembler ist ein Programm, welches Quellcode in Objektcode umwandelt. Mit
diesem Begriff identifiziert man auch häufig die Assemblersprache.
3.1. Darstellung von Befehlen
Befehlsstruktur
3+1
3+0
2+1
2+0
1+1
1+0
0+1
0+0
Adressen
a, b, c, d
a, b, c
a, b, d
a, b
a, d
a
d
keine
31
Wirkung (Beispiel)
ρ(a) = ρ(b) op ρ(c)
ρ(a) = ρ(b) op ρ(c)
ρ(a) = ρ(b) op ρ(a)
ρ(a) = ρ(b) op ρ(a)
α = α op ρ(a)
α = α op ρ(a)
goto d
Stackbefehl
Folgebefehl
d
β+1
d
β+1
d
β+1
d
β+1
α steht für den Akkumulator,
β bezeichnet den Befehlsfolgezähler und
ρ(i) ist der Wert (Datum) in Speicherzelle i
Häufig benutzt und ökonomisch, da nur auf maximal eine Adresse zugegriffen werden
muss, sind (1 + 0)-Befehle und (0 + 0)-Adressbefehle.
Abbildung 3.1: Befehlsstrukturen
(2 + y)-Adressbefehle sind aufwändiger und ungebräuchlich, sie lassen sich außerdem als eine Folge von (1 + y)- und (0 + 1)-Adressbefehlen darstellen.
Beispiel: (2 + 1)-Befehlssequenz
Der (2 + 1)-Befehl α = ρ(i) − ρ(k); goto h lässt sich durch folgende Sequenz simulieren:
α = ρ(i)
(1 + 0)-Befehl
α = α − ρ(k) (1 + 0)-Befehl
goto h
(0 + 1)-Befehl
Stack
Außer den vorgestellten Befehlen gibt es so genannte Stackbefehle, die auf dem
Stack arbeiten. Beim Stack handelt sich um eine Datenstruktur, die nach dem LIFOPrinzip (Last In First Out) organisiert ist. Ein Stack ist ein Stapel von Informationseinheiten, in die Informationen (Elemente) abgelegt werden. Dabei kann nur auf das
oberste Element zugegriffen werden. Es gibt zwei Operationen zur Veränderung des
Stacks.
• Push legt ein neues Element auf den Stack, das heißt, an die oberste Position
(τ, Top of Stack).
• Pop entnimmt das oberste Element, wobei das entnommene Element ausgegeben wird.
Es gibt auch eine Variante, bei der das oberste Element nicht ausgegeben wird.
In diesem Fall gibt es zusätzlich die Operation Top, welche es erlaubt, das
oberste Element des Stacks zu lesen, ohne dass es entfernt wird.
32
Kapitel 3. Maschinennahe Programmierung
Ein Stack wird als Folge σ = (σ(0), σ(1), . . . σ(τ)) notiert.
τ
..
.
σ(τ)
..
.
i
..
.
σ(i)
..
.
2 σ(1)
1 σ(0)
Beispiel: Simulation von Stackbefehlen
Der Push-Befehl vollzieht folgende Instruktionen:
τ = τ+1
σ(τ) = α
Pop lässt sich folgendermaßen ausdrücken:
α
τ
= σ(τ)
= τ−1
Sei nun stackadd die Operation, welche die obersten Stackelemente addiert, eliminiert und
die Summe als oberstes Element ablegt:
α
= σ(τ)
τ = τ−1
σ(τ) = α + σ(τ)
Anwendung finden Stacks bei der Auswertung arithmetischer Ausdrücke. Die Ausführung arithmetischer Operationen in Infixnotation (a op b) hängt von Präzedenzregeln und der Assoziativität der Operationen ab, wenn man von einer Klammerung
absieht. Die Umgekehrt Polnische Notation (UPN) legt die Auswertung von Ausdrücken eindeutig durch die Reihenfolge der Operanden und Operationen fest. Bei
dieser sukzessiven Auswertung im UPN-Ausdruck geht man von links nach rechts in
Verbindung mit Push, Pop und Stackφ vor, wobei φ ∈ {add, sub, mult, div, exp} ist.
Zur Auswertung eines Infixausdrucks wandelt man diesen zunächst in einen UPNAusdruck um. Hier stehen die Operationen hinter den Operanden.
Beispiel: Infixausdruck
Sei der Infix-Ausdruck x = a + [(b − c) · d] ↑ (e · f ) − g gegeben.
In UPN: x = abc − d · e f · ↑ +g−
Stackoperationen: Zu Beginn sei der Stack leer!
1
2
3
4
5
push a
push b
push c
stacksub
push d
3.1. Darstellung von Befehlen
6
7
8
9
10
11
12
13
14
stackmult
push e
push f
stackmult
stackexp
stackadd
push g
stacksub
pop x
3.1.2
Befehlstypen
Man unterscheidet folgende drei Befehlstypen nach ihren unterschiedlichen Aufgaben:
a) Datentransfer
Für den Datentransfer gibt es den Ladebefehl α = ρ(i), der Daten aus dem Speicher in den Akkumulator holt, und den Befehl ρ( j) = α zum Speichern für die
umgekehrte Richtung.
b) Arithmetische und logische Operationen
Beispiel für eine arithmetische Operation ist die Addition α = α + ρ(i).
Der Shiftbefehl zum Schieben von Bits in einem Speicherwort kann ebenfalls als
arithmetische Operation aufgefasst werden. Ein Shift nach links verdoppelt den
Wert (wenn man von Überträgen absieht).
Beispiel: Arithmetische und logische Operationen
SHR α, i führt einen Rechts-Shift des Akkumulatorinhalts um i Bits durch.
shr 2 , (0110111) = (0001101)
c) Steuerbefehle
• ein unbedingter Sprung
goto j
• ein bedingter Sprung
if <Bedingung> then goto k
<Bedingung> ist zum Beispiel α < 0 oder α = γ.
• ein Vergleich und Überspringen der nächsten Operation (Skip) bei Gleichheit
• ein Unterprogrammaufruf
call <Unterprogrammname/-adresse>
• ein Unterprogrammrücksprung
return
33
34
Kapitel 3. Maschinennahe Programmierung
3.1.3
Befehlssätze
Eine Menge von Befehlen eines Rechnermodells bezeichnet man als Befehlssatz.
Die meisten Befehle sind durch (eine Folge von) anderen Befehlen ersetzbar, also
simulierbar.
Es gibt nun die Tendenz zu möglichst großen Befehlssätzen mit komplexen Operationen. Hier lassen sich kurze Programme bei Ausnutzung des vollen Befehlssatzes
schreiben, denn es ist unnötig, umfangreichere Befehle durch eine Folge von weniger
mächtigen Befehlen zusammenzusetzen. Ein Rechner, der dieser Tendenz entspricht,
ist der Complete Instruction Set Computer (CISC)
Die RISC-Architektur (Reduced Instruction Set Computer) verfolgt gerade die umgekehrte Tendenz. Kleinere Befehlssätze lassen eine effizientere und schnellere Realisierung des Rechners zu.
Ferner geht man davon aus, dass komplexe Befehle selten eingesetzt werden und
bei Bedarf simuliert werden können; bei Beachtung des seltenen Eintretens ist der
Leistungsverlust gering. Die schnelle Realisierung der häufigen Grundoperationen
führt im Allgemeinen zu einer Leistungsverbesserung.
Beispiel: Befehlssimulation
Ein bedingter Sprung soll durch einen Vergleich-und-Skip-Befehl ersetzt werden.
Die Wirkung von skip α+ besteht darin, den nächsten Befehl zu überspringen, wenn α ≥
0.
Zu simulieren ist: if α < 0 then goto r
Simulation durch: [skip α+; goto r]; falls also α ≥ 0 ist, wird goto r übersprungen.
3.1.4
Verwendung zusätzlicher Register und Registerbefehle
Zusätzlich zum Akkumulator können weitere Register R0 , R1 , . . . zu speziellen Zwecken
benutzt werden, zum Beispiel als Indexregister γ.
In Registerbefehlen können bis zu drei dieser Register angesprochen werden:
• 0-Registerbefehle
Hierzu zählen die bisherigen Befehle. Im Falle der Verwendung des Akkumulators (Register) wird dieser nicht explizit genannt, sondern durch den Opcode
implizit angesprochen.
• 1-Registerbefehle
Beispiel eines solchen Befehls ist die Besetzung des Indexregisters zur indizierten Adressierung: γ = ρ(i). Der Opcode hat die Form:
Opcode
0
i
3.2. Adressierung
35
• 2-Registerbefehle
Ein Beispiel ist die Anwendung von Rechenoperationen auf Registerinhalte:
Ri = Ri − R j oder die Zuweisung (Laden) von Registerinhalten: Load Ri , R j ,
mit der Wirkung: Ri = R j . Der Opcode ist folgendermaßen aufgebaut:
Opcode
i
j
• 3-Registerbefehle
Analog lässt sich auch mit drei Registern rechnen: Ri = R j + Rk .
Die Verwendung von 3-Adressregisterbefehlen ist sinnvoll, weil diese Befehle
schnell ausführbar sind und kurze Adressen haben.
Beispiel: Registerbefehle
Seien 8 Register R0 , . . . , R7 gegeben. Die Registernummern werden mit Adressteilen zu je 3
Bits codiert, also insgesamt durch 3 · 3 = 9 Bits. Dementsprechend ist der Opcode wie folgt
aufgebaut:
Opcode
010
001
101
3.2 Adressierung
In diesem Abschnitt werden Techniken zum Ansprechen von Informationen im Speicher vorgestellt. Das Ansprechen von Speicher bezeichnet man auch als adressieren.
3.2.1
Direkte Adressierung (absolute Adressierung)
Bei der direkten Adressierung wird eine Speicherzelle durch Angabe der Adresse
adressiert. Hat diese eine Länge von k Bits, so können 2k Adressen angesprochen
werden. Man notiert diese direkte Adressierung in der Form α = ρ(100), wobei hier
beispielhaft der Akkumulator den Inhalt der Speicherzelle 100 erhält.
Der Vorteil dieser Technik liegt im einfachen und übersichtlichen Zugriff auf den
Speicher. Ein schwer wiegender Nachteil besteht aber darin, dass ein zu kleiner
Adressraum ansprechbar ist. Außerdem ist der Anteil der Adresse am Befehlswort
relativ hoch.
3.2.2
Indirekte Adressierung durch Basisregister und Relative Distanz
Diese Technik behebt die Nachteile der direkten Adressierung. Ein Befehl ist folgendermaßen aufgebaut:
Opcode
Nummer des Basisregisters i
m Bits
Relative Distanz j
r Bits
36
Kapitel 3. Maschinennahe Programmierung
Dabei stehen für die Nummer des Basisregisters m Bits und für die relative Distanz
r Bits zur Verfügung. Ist m = 3, so können die Register R0 , . . . , R7 der Länge h als
Basisregister fungieren (siehe Abbildung 3.2).
Beispiel zu indirekter Adressierung
r=12, m=3, h=4
Opcode
Basisadresse R5
m
r
5
j=1024
Block für
R5=0
Block für
R5=1
R0
angesprochene Adresse
R5
13
Block für
R5=13
Gesamtblock
für R5 mit 16
Blöcken und
jeweils
212 =4096 Bytes
Block für
R5=15
R7
h=4 Bits
Abbildung 3.2: Indirekte Adressierung mit Basisregister und relativer Distanz
Die Größe des adressierbaren Speichers ergibt sich somit aus:
Registerzahl
Registerinhalt
Rel. Verschiebung
2m
2h
2r
m=3
h=4
r = 12
→ 8 Register
→ 16 Blöcke pro Register
→ 0 ≤ j ≤ 4095
Es sind demnach 2m · 2h · 2r Speicherzellen mit einer m + r Bit langen Adresse ansprechbar (im Beispiel also 219 ). Mit direkter Adressierung sind dagegen nur 2m+r
Adressen ansprechbar. Die Wortlänge des Befehls wurde eigentlich um h Bits verlängert durch den Zugriff auf das h-Bit-Register Ri .
Durch Verwendung vernünftig großer Registerlängen ist ein fast unbeschränkt großer
Speicherbereich auf diesem Wege adressierbar.
Bisher war die Basisadresse fest. Durch Änderung dieser Adressen ist eine weitere
Flexibilisierung möglich.
3.2.3
Indexregister zur indirekten Adressierung
Sei γ ein Indexregister. Durch geeignete Belegungen von γ lassen sich praktisch beliebige Adressen angeben. Im Zusammenhang mit diesem Register kann man zum
Beispiel folgende Befehlstypen verwenden:
• α = ρ(γ)
• ρ(γ) = α
3.2. Adressierung
37
• γ = γ−1
Anwendung findet das Indexregister bei der Bearbeitung von linearen Listen, Schleifen und ähnlichem ohne Änderung des Adressteils eines Befehls.
Beispiel: Indexregister in einer Schleife
1
2
3
4
5
6
7
8
9
3.2.4
ANFANG :
γ = 1000
//Vorbesetzung
.
.
//Andere Operationen denkbar
α = ρ(γ) // Nacheinander werden ρ(1000),. . .
.
// ρ(999), . . . , ρ(1) angesprochen
.
.
γ = γ−1
if γ > 0 then goto ANFANG
Indexregister mit Adressmodifikation
Um zwischen direkter und indizierter Adressierung wählen zu können, bietet sich
diese Technik an. Der Befehl hat die folgende Struktur:
Opcode
j
Adresse
j kann dabei zum Beispiel mit 3 Bits codiert sein und gibt folgende Situationen an:
j=0
j ∈ {1, . . . 7}
3.2.5
Befehl ohne Adressmodifikation, Befehl α = ρ(Adresse)
Adressmodifikation mit Indexregister γ j , Befehl α = ρ(Adresse + γ j )
Unterschiedliche Adressmodi
Ferner sind Modifikationen der Adresse denkbar. So wird je nach Modus zum Beispiel das Indexregister automatisch inkrementiert, wenn über dieses eine Adressierung vorgenommen wird.
3.2.6
Indirekte Adressierung
Eine weitere Variante ist die indirekte Adressierung, bei der die Adresse einer Speicherzelle als Inhalt einer anderen Speicherzelle ermittelt wird. Ein Holebefehl hat
dann die Form α = ρ(ρ(i)) während er bei direkter Adressierung α = ρ(i) lautete.
In einem Befehl ist die Kennzeichnung, ob α = ρ(i) oder α = ρ(ρ(i)) gemeint ist,
durch das I-Bit möglich; zum Beispiel zeigt I = 0 die direkte und I = 1 die indirekte
Adressierung an.
38
Kapitel 3. Maschinennahe Programmierung
Beispiel: Indirekte Adressierung
Bearbeitung der Zellen 100, 99, . . . , 1 mit indirekter Adressierung:
α = 100
1
2
3
4
5
6
7
8
9
10
START :
ρ(200) = α // Hilfsspeicherzelle 200
α = ρ(ρ(200))
.
.
.
α = ρ(200)
α = α−1
if α > 0 then goto START
3.2.7
Modifizierung von Befehlen
Der Inhalt des Adressteils eines Befehls wird hier modifiziert, also etwa inkrementiert
oder dekrementiert. Die Wirkung besteht darin, dass das Programm während seines
Durchlaufs verändert wird. Dies ist zum Teil undurchschaubar und daher gefährlich.
3.3 Leistungsfähigkeit von Adressiertechniken
Satz: Mächtigkeit von Adressiertechniken
Die Adresstechniken, welche indirekte Adressierung erlauben, besitzen die volle Funktionalität der absoluten Adressierung, bzw. sind sogar noch stärker.
Beweisidee:
1. Jede der Techniken kann durch jede andere simuliert werden.
2. Problem: siehe nachfolgende Vermutung!
Ist die direkte Adressierung schwächer als eine indirekte Adressierung? Unter schwächer ist dabei zu verstehen, dass es ein Problem gibt, zu dessen Lösung ein Programm
mit indirekter Adressierung existiert, aber keines, welches allein mit direkter Adressierung auskommt.
Es stellt sich heraus, dass diese Behauptung nicht allgemein gilt, sondern von der
Endlichkeit des Rechnermodells abhängt.
3.3.1
Berechnung durch ein Programm
Zur Diskussion der Vermutung müssen wir uns mit der Frage befassen, was ein Programm eigentlich berechnet.
3.3. Leistungsfähigkeit von Adressiertechniken
Ein (terminierendes) Programm soll eine Fragestellung universell lösen, das heißt,
ein und dasselbe Programm wird auf verschiedene Argumentkombinationen angesetzt (siehe Beispiel: Additionsprogramm). Es bewirkt im Wesentlichen eine Transformation eines alten Rechenspeicherinhalts in einen neuen Rechenspeicherinhalt. Im
Wesentlichen soll heißen: Ein- und Ausgabe nur vom oder zum Speicher; Register,
Flags und Statusinformationen sind nur für Hilfszwecke vorgesehen, also unerheblich für das Start- beziehungsweise Endergebnis. Damit kann man ein Programm als
eine Abbildung vom Rechenspeicher in den Rechenspeicher (RSP) auffassen.
f : RSP → RSP
Beispiel: Additionsprogramm
1
2
3
4
5
6
7
γ = 100
α=0
//Initialisierung: Anfangssumme
α = α + ρ(γ) //Indirekte Adressierung
γ = γ−1
if γ > 0 then goto 2
ρ(1) = α
HALT
In diesem kurzen Programm sei es erlaubt, Zahlen als Label zu verwenden, die an sich keine
Aussage über die Programmstruktur zulassen. Daher sollte man bei längeren Assemblerprogrammen aussagekräftige Label verwenden. Die Wirkung des Programms ist in folgender
Abbildung dargestellt.
RSPalt
0
1
100
M−1
3.3.2
ρ(1)
ρ(100)
0
1
RSPneu
=
neu
=
100
=
M−1
=
← ρ(1)alt + ρ(2)alt + · · · + ρ(100)alt
= heißt unveränderter Inhalt
Endlichkeit der realen Maschine
Wir betrachten zunächst die Berechenbarkeit, die auf der Endlichkeit einer realen
Maschine basiert. Jede Rechenspeicherzelle ist endlich groß, daher ist auch jedes Programmspeicherwort endlich groß. Diese obere Schranke soll nicht vergrößert werden
können (etwa durch längere Worte).
Die Information einer Rechenspeicherzelle sei o.B.d.A. eine ganze Zahl, die kleinste
darstellbare Zahl sei mit MINZAHL und die größte darstellbare Zahl mit MAXZAHL
bezeichnet.
Ein Programm, das M Speicherzellen verwendet, ist auffassbar als Abbildung
f : D → D′ , wobei D, D′ ⊆ [MINZAHL : MAXZAHL]M
39
40
Kapitel 3. Maschinennahe Programmierung
Beispiel: Additionsprogramm
Das vorige Additionsprogramm hatte 100 Eingangsargumente und 1 Ausgangswert, also
gilt hier
D = [MINZAHL : MAXZAHL]100 und
D’ = [MINZAHL : MAXZAHL]1 .
Satz: Realisierbarkeit von Abbildungen durch Programme
Jede Abbildung f : D → D′ mit D, D′ ⊆ [MINZAHL : MAXZAHL]M ist realisierbar durch
ein Programm, welches (außer Steuerbefehlen wie START, STOP,. . .) auskommt mit:
α = ρ(i)
für i, j ∈ [0, . . . , M − 1]
ρ( j) = α
i und j sind absolute Adressen, keine Variablen
α=k
k ist Konstante
α = α±1
In-/Dekrementierung des Akkumulatorinhalts
if α < 0 then goto j
if α = 0 then goto j
if α > 0 then goto j
Dieses Programm kommt insbesondere ohne indirekte Adressierung und mit einem
sehr kleinen Befehlssatz aus.
Beweis:
Beweis (für jedes Programm, also für jede Abbildung f ):
Die Abbildung f bewirkt: f (ρ(0)alt , . . . , ρ(M − 1)alt ) = (ρ(0)neu , . . . , ρ(M − 1)neu ),
wobei: ρ(k)neu = hk (ρ(0)alt , . . . , ρ(M − 1)alt ). Das heißt, der neue Wert ergibt sich aus den
alten Werten (im Extremfall aus allen alten Werten).
Beispiel: voriges Additionsprogramm
k 6= 1: ρ(k)neu = hk (. . .) = ρ(k)alt
k = 1: ρ(1)neu = h1 (ρ(1)alt , . . . , ρ(100)alt ) = ρ(1)alt + . . . + ρ(100)alt
also:


5050 falls ρ(i)alt = i, 1 ≤ i ≤ 100
h1 (ρ(1)alt , . . . , ρ(100)alt ) = 0
falls ρ(i)alt = 0, 1 ≤ i ≤ 100


...
andere Fälle
Die Programmwirkung ist also beschreibbar durch Abbildungen h0 , h1 , . . . hM−1 .
Abbildung 3.3 zeigt, wie die Eingangsargumente ρ(i)alt schichtweise im Baum abgefragt werden. Somit ist jede Kombination von Eingabeargumenten durch einen Pfad
im Baum gegeben. An den Blättern erhält man aufgrund der Funktionen h1 bis hM−1
und der durch den Pfad gegebenen Eingangswerte die Ausgabeargumente.
Das folgende Programm realisiert diese schichtenweise Abfrage der Eingangsargumente im Wesentlichen unter Verwendung bedingter Sprünge. Die Ausgabeargumente werden im letzten Abschnitt des Programms eingetragen.
Sei zur Abkürzung: MINZAHL = −Q und MAXZAHL = +Q.
0:
1:
2:
3:
α = ρ(0)
if α = 0 then goto [ Stufe 2 , Wert 0] Label mit Nummer 4 Q +1
if α < 0 then goto (2 Q +2)
α = α−1
3.3. Leistungsfähigkeit von Adressiertechniken
Stufe 1:
Abfrage von
(0)alt
41
(0)
=Minzahl
=Minzahl
(1)
=Maxzahl
(1)
(1)
(2)
(M-1)
=Minzahl
Eintragen
h0(Min,…,Min,Min)
h1(Min,…,Min,Min)
.
.
.
hM-1(Min,…,Min,Min)
=Maxzahl
=Minzahl+1
Stufe M:
Abfrage von
(M-1)alt
Eintragen
h0(Min,…,Min,Min,Max)
h1(Min,…,Min,Min,Max)
.
.
.
hM-1(Min,…,Min,Min,Max)
Abbildung 3.3: Algorithmus zur Berechnung von h0 , h1 , . . .
4: if α = 0 then goto [ Stufe 2 , Wert 1]
5: α = α − 1
6: if α = 0 then goto [ Stufe 2 , Wert 2]
.
2Q : if α = 0 then goto [ Stufe2 , Wert Q - 1]
2Q +1: goto [ Stufe 2 , Wert Q]
2Q +2: α = α + 1
2Q +3: if α = 0 then goto [ Stufe 2 , Wert - 1]
.
4Q -1: if α = 0 then goto [ Stufe 2 , Wert - Q + 1]
4Q : goto [ Stufe 2 , Wert - Q]
4Q +1 [ Baumorganisation Stufe 1 , 2 ,. . ., M]
Letzte Stufe zur Eintragung der Ergebnisse :
α = h0 (−Q, . . . , −Q) zum Beispiel : α = +17
ρ(0) = α
α = h1 (−Q, . . . , −Q) zum Beispiel : α = −3
ρ(1) = α
.
α = h(M−1) (−Q, . . . , −Q)
ρ(M − 1) = α
.
α = h0 (−Q, −Q, −Q, −Q + 1)
ρ(0) = α
.
42
Kapitel 3. Maschinennahe Programmierung
3.3.3
Beliebig große Funktionswerte sollen berechenbar sein
Ein Beispiel ist die Addition beliebig großer Zahlen. Das Programm ist jetzt eine
Abbildung:
f : [MINZAHL : MAXZAHL]∗ → [MINZAHL : MAXZAHL]∗
Das * zeigt an, dass es beliebig viele Rechenspeicherzellen gibt.
Satz: Indirekte Berechnung von Abbildungen durch Programme
Es gibt Abbildungen, die nur durch Programme mit indirekter Adressierung berechenbar
sind.
Diese Programme enthalten also Befehle der Art ρ(ρ(i)) = α oder ρ(γ) = α.
Beweis:
Ein Programm ohne indirekte Adressierung spricht nur feste Rechenspeicherzellen durch
Befehle der Form ρ(i) = α an. Jedes Programm P hat eine maximale, von ihm angesprochene Rechenspeicheradresse ADMAX(P). Hinter ADMAX(P) kann im Rechenspeicher
nichts geändert werden. Daher sind alle Probleme, die hinter ADMAX(P) etwas ändern,
von P nicht bearbeitbar.
Beispiel: Beispiel für Existenz solcher Probleme
Suche die erste 0 im Rechenspeicher und ersetze sie durch 1.
Hier kann nämlich die erste 0 hinter ADMAX(P) liegen.
Annahme: Es existiere ein Programm P ohne indirekte Adressierung.
Man betrachte die Rechenspeicherbelegung, bei der keine 0 in den Speicherzellen mit einer
Adresse kleiner/gleich ADMAX(P) steht.
Für diese Speicherbelegung versagt das Suchprogramm P.
Also ein Widerspruch.
Mit indirekter Adressierung geht es sehr einfach:
1
2
3
4
5
6
γ = −1
γ = γ+1
α = ρ(γ)
if (α 6= 0) then goto 1
ρ(γ) = 1
HALT
3.4 Unterprogramme
Beim Programmaufbau aus Modulen werden oft benutzte Teile als Unterprogramm
(UP) zusammengefasst. Diese können auch in Form einer Unterprogrammbibliothek abgerufen werden, was der Wiederverwendbarkeit dient. In diesem Abschnitt
werden nun Probleme aufgezeigt, die sich bei der Handhabung solcher Unterprogramme auf maschinennaher Ebene ergeben.
Ein Unterprogramm habe die folgende Form:
3.4. Unterprogramme
UP
43
← Aufruf
Name, Parameter
.
.
.
Ergebnisse
→ Rücksprung
Unterprogramme sind möglicherweise mehrstufig verschachtelt, das heißt, ein Unterprogramm ruft ein anderes oder sich selbst auf. Einen Ablauf einer solchen Aufrufkette zeigt die Abbildung 3.4.
Hauptprogramm
UP1
UP2
Zeti
UP3
UP4
UP5
UP6
Abbildung 3.4: Aufruf und Beenden von Unterprogrammen
Die Pfeile → kennzeichnen die Unterbrechung des Unterprogramms der Ebene i und
den Aufruf des Unterprogramms der Stufe (i + 1). Die Pfeile in umgekehrter Richtung zeigen die Beendigung des Unterprogramms der Stufe (i + 1) und den Wiedereintritt in das aufrufende Unterprogramm der Stufe i an.
Ein Problem ist es nun, die richtige Einsprungstelle für den Wiedereintritt zu verwalten. Die unterschiedlichen Techniken bedingen folgende Kategorien von Unterprogrammen.
3.4.1
Einstufige, nichtrekursive Unterprogramme
Die Speicherposition des aufrufenden Programms wird im Register δ gespeichert.
Ein Unterprogrammaufruf durch call legt die Adressse des call-Befehls, also
des aufrufenden Programms, in δ ab. Ein return aus dem Unterprogramm führt zu
einem Sprung an die nächste Adresse nach der geretteten Programmadresse in δ.
Weil nur eine Zelle (Register) zur Verwaltung der Adresse des aufrufenden Programms verwendet wird, kann auch nur eine Verzweigung in ein Unterprogramm
durchgeführt werden. Daher nennt man diese Programme einstufig. Insbesondere ist
Rekursion unmöglich (siehe Abbildung 3.5).
44
Kapitel 3. Maschinennahe Programmierung
k:
call j
.
.
.
Unterprogramm
j:
.
.
.
.
.
return
Seiteneffekt: =k;
goto j
Seiteneffekt: goto
Abbildung 3.5: Einstufiger Unterprogrammaufruf
3.4.2
Mehrstufige, nichtrekursive Unterprogramme
Bei dieser Technik hat jedes Unterprogramm eine eigene Rücksprungadresse. Sie
ist an einer speziellen Stelle dessen gespeichert und gibt an, an welcher Stelle in
dem aufrufenden (Unter-) Programm fortzufahren ist, wenn das aufgerufene Unterprogramm selbst beendet ist. In Abbildung 3.6 ist diese Rücksprungadresse an der
ersten Stelle des aufgerufenen Unterprogramms abgelegt ρ( j).
i:
j:
j+1:
call j
.
.
.
[Zunächst frei für Rücksprungadresse]
Start UP
.
.
.
return
Wirkung: (i):=i+1; goto j+1;
d.h. rette Rücksprungadresse
im ersten (dafür frei zu
haltenden) UP-Befehl
Wirkung: goto (j)
Abbildung 3.6: Mehrstufiger Unterprogrammaufruf
Eine Voraussetzung für die Funktionsfähigkeit dieser Technik besteht darin, dass das
Unterprogramm sich nicht selbst aufruft (reentrent ist); in diesem Falle würde die
Rücksprungadresse überschrieben werden.
3.4.3
Mehrstufige, eventuell rekursive Unterprogramme
Zunächst wird ein Beispiel eines typischen rekursiven Unterprogramms gegeben. Es
handelt sich um die rekursive Berechnung der Fakultätsfunktion (n!).
1 int fakultaet (int n ) {
3.4. Unterprogramme
2
3
4
5
6
7
8
45
if ( n ==0 || n ==1) {
return 1;
}
else {
return n* fakultaet (n -1);
}
}
Ein Aufruf von f (n) = f akultaet(n) zieht die folgende Kette von rekursiven Unterprogrammaufrufen nach sich:
ruft auf
ruft auf
ruft auf
zurück
zurück
zurück
f (n) −→ f (n − 1) −→ f (n − 2) −→ . . . f (1)
f (n) ←− f (n − 1) ←− f (n − 2) ←− . . . f (1)
Die Technik des letzten Abschnitts ist nicht anwendbar, da nur eine Speicherzelle für
die Rücksprungadresse vorgesehen ist. An dieser Stelle müssten also beliebig viele
Stellen für Rücksprungadressen zur Verfügung stehen, anhand derer man ablesen
kann, welche die nächste Rücksprungadresse ist. Hierfür eignet sich der Stack, wobei
die letzte Rücksprungadresse das Topelement ist.
Rekursive Aufrufe werden also über einen Stack mit den Operationen Push und Pop
verwaltet, wobei folgende Register verwendet werden.
• δ1: Register, dessen Inhalt auf die oberste Stackposition (Topelement) zeigt (für
Push und Pop).
• δ2: Befehlszählregister (enthält Adresse des aktuellen Befehls).
• RL : Das so genannte Linkageregister ist ein beliebiges Register zum Auslesen
der Parameter im Unterprogramm und Speichern der Rücksprungadresse.
Der call- und return-Befehl haben dann die Wirkung:
• call RL ,dst
[push RL ; RL = δ2 + 1; goto dst]
• return RL
[pop RL ;δ2 = RL ]
Dabei ist dst die erste Adresse des aufgerufenen Unterprogramms:
dst :
< Unterprogramm - Anweisungen >
Der call-Befehl sichert den aktuellen Wert des Linkageregisters auf dem Stack und
setzt RL auf die Adresse des ersten Parameters.
Das Unterprogramm liest die Parameter mittels Autoinkrementadressierung über RL ,
so dass RL anschließend auf den nächsten Befehl zeigt. Dieser ist die Rücksprungadresse. Der return-Befehl setzt das Befehlszählregister auf die Rücksprungadresse
und holt den alten Wert von RL vom Stack.
46
Kapitel 3. Maschinennahe Programmierung
Eine andere Organisationsform für die Verwaltung der Ein- und Ausgabeparameter
verwendet zwei besondere Register: REING und RRESULT sollen die Rechenspeicheradressen enthalten, in denen die Eingangsparameter beginnen beziehungsweise ab
wo die Ergebnisse zurückzuschreiben sind. Diese müssen (bei Aufruf des Unterprogramms) geeignet vorbesetzt werden. Die Eingangsparameter werden sofort übernommen (das heißt, es ist hierfür kein Stack notwendig). RRESULT wird über einen
Stack verwaltet. Der zugehörige Unterprogrammaufruf sieht schematisch wie folgt
aus.
Hauptprogramm
.
.
Vorbesetzung RResult
PUSH RResult → Resultstack
Vorbesetzung REING
call dst [ Wirkung α = δ2 + 1; Push α → Rücksprungstack ]
.
.
------dst :
α = REING
Übernahme Eingangsargumente
.
.
α = Oberstes Element Resultstack
α = ρ(α)
Übergabe Ergebnisse
return [ Wirkung : α =Oberstes Element des Rücksprungstacks ;
goto α]
REING und RRESULT verweisen auf den Beginn der Eingangs- bzw. Ergebnisparameterblöcke.
Damit man weiß, wie viele Argumente zu übergeben sind, kann man in der ersten
Zelle dieser Bereiche jeweils die Anzahl der zu übergebenden Parameter plus die
Länge selbst speichern.
REING
k=Länge
Argument 1
Argument 2
..
.
Argument k − 1
..
.
RRESULT
k=2
Ergebnis
KAPITEL 4
Bausteine und Komponenten von
Rechensystemen
In diesem Kapitel wird die rechnerinterne Verarbeitung von Informationen mittels
Schaltungen, Schaltkreisen und Schaltwerken betrachtet.
4.1 Schaltfunktionen, Bausteinsysteme und Boolesche Algebra
Die Aufgabe einer Schaltung besteht in der Transformation (binär dargestellter) Eingangssignale in (binär dargestellte) Ausgangssignale. Eine Schaltung ist daher mit
einem Programm vergleichbar, mit dem Unterschied, dass die Transformation durch
die Schaltung fest verdrahtet ist. Eine Schaltfunktion beschreibt die Zuordnung von
Ausgangswerten zu Eingangswerten.
Beispiel: LED-Dezimalzähler
Als erstes Beispiel für eine Schaltung wird ein LED-Zähler betrachtet. Der LED-Zähler
besteht aus 7 Strichen, die leuchten oder nicht leuchten.
x0
x3
x4
x1
x2
x5
x6
Beispielsweise lässt sich die 7 durch Aufleuchten der Striche x0 , x5 und x6 darstellen. Dies
entspricht dem Setzen von Bits (x0 , x1 , . . . , x6 ) = (1, 0, 0, 0, 0, 1, 1). Dem entsprechend ist
der 4 (0, 1, 0, 1, 0, 1, 1) zugeordnet. Ein LED-Zähler soll nun von 0 bis 9 mod 10 zählen. Er
muss also zur aktuellen Zahl i (Eingangswert) den Nachfolger (i + 1) mod 10 (Ausgangswert) erzeugen, wie folgende Abbildung veranschaulicht.
47
48
Kapitel 4. Bausteine und Komponenten von Rechensystemen
x0
x0,Neu
x1
x1,Neu
x2
x3
x4
Schaltung,
Schaltkreis,
Schaltznetz
x2,Neu
x3,Neu
x4,Neu
x5
x5,Neu
x6
x6,Neu
Definition: Schaltung
Die Wirkung einer Schaltung wird durch eine n-stellige Schaltfunktion mit k Ausgängen
beschrieben.
f : Bn −→ Bk mit B = {0, 1}
x0
y0
n-stellige
Schaltfunktion
yk-1
xn-1
Möglicherweise kann nur ein Teil aller denkbaren Eingangssignale (Kombinationen
der xi in Form von (x0 , x1 , . . . , xn−1 ) vorkommen. In diesem Fall gilt: f : Bn ⊃ D → Bk .
Auf dem Eingangsbereich Bn \D ist die Schaltfunktion undefiniert und somit in ihren
Ausgangswerten frei wählbar. Diesen Bereich bezeichnet man auch als Don’t CareBereich.
Beispiel: Schaltfunktion
Beim LED-Zähler werden nur 10 Kombinationen der 27 möglichen benutzt. Es ist zum
Beispiel dem Leuchten der Striche drei, vier und sechs keine Zahl sinnvoll zuzuordnen.
Eine n-stellige Schaltfunktion kann in Form einer Tabelle angegeben werden, indem
man in die linke Spalte die definierten Eingangswerte und in die rechte Spalte die die
Funktion definierenden Ausgangswerte schreibt:
Ausgänge
Eingänge
xn−1 , . . . , x0 yk−1 , . . . , y0
0...0
...
..
..
.
2n Zeilen inklusive Don’t Cares
.
1...1
...
4.1. Schaltfunktionen, Bausteinsysteme und Boolesche Algebra
Im Falle, dass die Funktion n-stellig und jede Komponente binär ist, sind maximal 2n
Werte des Definitionsbereichs und dem entsprechend viele Ausgangswerte denkbar.
Beispiel: Rückwärtszähler im 3-Excess-Code
Die folgende Tabelle zeigt die Schaltfunktion für einen Rückwärtszähler im 3-ExcessCode, der in Abschnitt 2.4 eingeführt wurde. Die Aufgabe besteht in der Beschreibung
der Funktion:
f : B4
[i]3-Excess
Dezimaler Wert
0
1
2
3
4
5
6
7
8
9
x3
0
0
0
0
0
1
1
1
1
1
0
0
0
1
1
1
x2
0
1
1
1
1
0
0
0
0
1
0
0
0
1
1
1
→
7
→
B4
[(i − 1) mod 10]3-Excess
x1
1
0
0
1
1
0
0
1
1
0
0
0
1
0
1
1
x0
1
0
1
0
1
0
1
0
1
0
0
1
0
1
0
1
y3
1
0
0
0
0
0
1
1
1
1
y2
1
0
1
1
1
1
0
0
0
0
y1
0
1
0
0
1
1
0
0
1
1
y0
0
1
0
1
0
1
0
1
0
1
Dezimaler Wert
9
0
1
2
3
4
5
6
7
8
Don’t Care
Werte
Eine Schaltfunktion mit k Ausgängen ist darstellbar durch k Schaltfunktionen auf
dem gleichen Definitionsbereich mit je einem Ausgang:


Bn → B

 f0
.
f : Bn → Bk entspricht ..


f
n
k−1 B → B
Aus diesem Grund kann man sich auf Schaltfunktionen mit einem Ausgang beschränken.
4.1.1
Entwurf und Realisierung von Schaltfunktionen
In diesem Abschnitt werden Bausteine eingeführt, die es gestatten, binäre Eingangswerte in binäre Ausgangswerte zu überführen. Man kann sie als Operationen auf B
auffassen. Es bestehen nun die Fragen
• Welche Bausteine sind notwendig, um bestimmte Eigenschaften der Schaltfunktion wiederzugeben?
49
50
Kapitel 4. Bausteine und Komponenten von Rechensystemen
• Wie kann man eine Schaltfunktion mit möglichst wenigen Bausteinen darstellen, um den Realisierungsaufwand und damit die Kosten gering zu halten?
Dabei soll der Entwurf möglichst systematisch sein. Besonders einfache Schaltfunktionen lassen sich als Grundbausteine (Bausteinfunktionen) zur Zusammensetzung
komplexerer Funktionen verwenden. In der folgenden Tabelle sind einige Symbole
für solche Grundbausteine dargestellt.
Name
Konjunktion
(AND)
Definition
ANDn : Bn → B
AND(x0 , . . . , xn−1 ) = 1 ⇔
x0 · . . . · xn−1 = 1
Disjunktion (OR)
ORn : Bn → B
OR(x0 , . . . , xn−1 ) = 0 ⇔
x0 + . . . + xn−1 = 0
Negation (NOT)
NAND
NOR
XOR
EQUIV
Schwellenelemente
Symbol
NOT : B → B
NOT (x) = 1 − x = x̄
NANDn : Bn → B
NAND(x0 , . . . , xn−1 ) = 1 ⇔
x0 · . . . · xn−1 = 0
NORn : Bn → B
NOR(x0 , . . . , xn−1 ) = 1 ⇔
x0 + . . . + xn−1 = 0
XORn : Bn → B
XOR(x0 , . . . , xn−1 ) = (x0 + . . . + xn−1 )
mod 2
EQUIVn : (x0 , . . . , xn−1 ) = XORn
σk : B n → B
σk (x0 , . . . , xn−1 ) = 1 ⇔
x0 + . . . + xn−1 ≥ k
Die XOR-Funktion (auch EXOR) kann als Parityfunktion verwendet werden, wie
zum Beispiel im Abschnitt über Darstellung von Zeichen in Kapitel 2 beschrieben.
Die EXOR-, NOT- und EQUIV-Funktion sind keine Schwellenelemente. Für das
logische AND schreibt man ∧, ∩ oder ·. Das OR wird als ∨, ∪ oder + geschrieben.
AND bindet stärker als OR.
Definition: Bausteinsystem
Eine Menge von Bausteinfunktionen, aus denen sich beliebige Schaltfunktionen zusammensetzen lassen, heißt Bausteinsystem.
4.1. Schaltfunktionen, Bausteinsysteme und Boolesche Algebra
51
Beispiel: Einige Bausteinsysteme
Bausteinsystem
{AND2 , OR2 , NOT }
{AND2 , NOT }
{OR2 , NOT }
{NAND2 }
{NOR2 }
{AND2 , XOR2 , 1}
{σk , NOT }
Nachweis
Disjunktive und konjunktive Normalform
OR2 (x, y) = NOT (AND2 (NOT (x), NOT (y)))
AND2 (x, y) = NOT (OR2 (NOT (x), NOT (y)))
NOT (x) = NAND2 (x, x), AND2 = NOT (NAND2 )
Analog zu {NAND2 }
Komplementfreie Ringsummenentwicklung
σ1 = ORn , σn = ANDn
Schaltfunktionen lassen sich mit diesen Grundbausteinen zu beliebigen neuen Schaltfunktionen zusammensetzen.
Zusammensetzung Neue Schaltfunktion Definition
x0
xn-1
f
xn-1
x0
g
fg
x0
xn-1
f
xn-1
( f · g) : Bn → B
( f · g)(x0 , . . . , xn−1 )
AND2 ( f (. . .), g(. . .))
=
( f ∪ g) : Bn → B
( f ∪ g)(x0 , . . . , xn−1 )
OR2 ( f (. . .), g(. . .))
=
x0
g
f+g
xn-1
x0
xn-1
x0
f
f
f¯(x0 , . . . , xn−1 ) = NOT ( f (. . .))
Definition: Gleichheit von Schaltfunktionen
Zwei Schaltfunktionen f : D → B und g : D → B heißen genau dann gleich, wenn sie für
alle zulässigen Argumentkombinationen das gleiche Ergebnis liefern:
f = g ⇔ f (x0 , . . . , xn−1 ) = g(x0 , . . . , xn−1 ) für alle (x0 , . . . , xn−1 ) ∈ D
Eigenschaften des Zusammensetzungsprozesses von Schaltfunktionen:
f ∧g = g∧ f
( f ∧ g) ∧ h = f ∧ (g ∧ h)
f ∧ (g ∨ h) = ( f ∧ g) ∨ ( f ∧ h)
f ∧ ( f ∨ g) = f
f ∧ (g ∨ ḡ) = f
Definition: Boolesche Algebra
Eine Menge A mit drei Operationen
F1: Kommutativität
F2: Assoziativität
F3: Distributivität
F4: Absorbtion
F5: Komplement
f ∨g = g∨ f
( f ∨ g) ∨ h = f ∨ (g ∨ h)
f ∨ (g ∧ h) = ( f ∨ g) ∧ ( f ∨ h)
f ∨ ( f ∧ h) = f
f ∨ (g ∧ ḡ) = f
52
Kapitel 4. Bausteine und Komponenten von Rechensystemen
• · : A×A → A
• + : A×A → A
• ¯ :A→A
heißt Boolesche Algebra (A, ·, +, ¯ ) genau dann, wenn die Axiome F1 bis F5 erfüllt sind.
Hieraus kann man folgern, dass die Menge der Schaltfunktionen mit den Operationen
AND2 , OR2 und NOT eine Boolesche Algebra bilden.
Es sind auch andere Axiomensysteme denkbar, wie zum Beispiel eines, welches
die Kommutativität (K), die Distributivität (D), das neutrale Element (N) und die
Komplementfunktion (C) umfasst. Dabei gibt es Entsprechungen zwischen (K) und
F1 sowie (D) und F3. Die anderen Axiome lauten:
(N) Es gibt neutrale Elemente 0, 1 ∈ A mit f + 0 = f und f · 1 = f
(C) Die Komplementfunktion zu f erfüllt: f + f¯ = 1 und f · f¯ = 0 für alle f ∈ A
Satz: Äquivalenz zwischen Axiomensystemen
Die Axiome F1 bis F5 sind äquivalent zu den Axiomen (K), (D), (N) und (C).
Andere Bausteinsysteme verwenden die Schaltfunktionen 0 und 1.
0 : Bn → B mit 0(x0 , . . . , xn−1 ) = 0
1 : Bn → B mit 1(x0 , . . . , xn−1 ) = 1
für alle (x0 , . . . , xn−1 ) ∈ Bn
Andere Beispiele für Boolesche Algebren sind:
• Aussagenkalkül, wobei eine Aussage den Wahrheitswert wahr oder falsch
annimmt. Dabei lassen sich Aussagen wie Schaltfunktionen zusammensetzen.
• Mengenalgebra mit den Operationen Durchschnitt, Vereinigung und Komplementmenge.
Satz: Satz von Stone
Jede endliche Boolesche Algebra (A, op 1 , op 2 , op 3 ) ist isomorph zu einer Mengenalgebra (℘(M), ∪, ∩, ¯ ). Das heißt, es gibt eine Bijektion ϕ : A → ℘(M) mit
ϕ(x op 1 y) = ϕ(x) ∪ ϕ(y)
ϕ(x op 2 y) = ϕ(x) ∩ ϕ(y)
ϕ( op 3 x)
= ϕ(x)
Beachten Sie, dass ℘(M) die Potenzmenge von M ist.
Die folgende Skizze veranschaulicht die Aussage des Satzes, wobei hier beispielhaft
op 1 und ∪ aufgeführt werden.
4.1. Schaltfunktionen, Bausteinsysteme und Boolesche Algebra
ϕ
x, y −−−−→ ϕ(x), ϕ(y)


 op
∪
y 1
y
ϕ
x op 1 y −−−−→ ϕ(x) ∪ ϕ(y)
Das Diagramm ist kommutativ: man kann in der Mengenalgebra ebenso rechnen wie
in der Algebra A. Daher kann man alle Eigenschaften endlicher Boolescher Mengen
als Eigenschaften von Mengenalgebren interpretieren. Dies kann dem leichteren Verständnis von Aussagen dienen.
Beispiel: Schaltfunktion vs. Boolesche Algebra
Die Aussage (F3)DUAL f ∨ (g ∧ h) = ( f ∨ g) ∧ ( f ∨ h) wird in der folgenden Abbildung
deutlich.
f
g
h
Weitere Eigenschaften endlicher Boolescher Algebren sind somit aus Axiomen oder
auch durch mengentheoretische Interpretation herleitbar, wie etwa:
a∧0 = 0
a∨1 = 1
a∧a = a
a∨a = a
a ∧ b = ā ∨ b̄
a ∨ b = ā ∧ b̄
(Gesetz von de Morgan)
a∪b = b ⇔
a∩b = a ⇔
ab̄ = 0 ⇔
ā ∪ b = 1 ⇔
b ⊃ a (mengentheoretische Interpretation)
ā¯ = a 0̄ = 1 1̄ = 0
Eine weitere Folgerung aus dem Satz von Stone ist der folgende Satz.
Satz: Anzahl der Elemente einer Booleschen Algebra
Jede endliche Boolesche Algebra hat eine Elementanzahl, die eine Zweierpotenz ist.
53
54
Kapitel 4. Bausteine und Komponenten von Rechensystemen
Beispiel: Anzahl der Elemente einer Schaltfunktion
Sei S(D) die Menge der n-stelligen Schaltfunktionen mit D Zeilen:
S(D) = { f | f : Bn ⊃ D → B}
Dann hat S(D) 2|D| Elemente. Diese Elemente stellen alle kombinatorisch denkbaren Wertebereiche der n-stelligen Schaltfunktion dar.
Beweis: Jede der D Zeilen ist unabhängig von den anderen mit dem Ausgangswert 0 bezie2
n
hungsweise 1 besetzbar. Insbesondere gilt: S(Bn ) = 22 . Sei n = 2, so ergeben sich 22 = 16
Schaltfunktionen, wie in folgender Tabelle aufgeführt:
x1
0
0
1
1
x0
0
1
0
1
f0
0
0
0
0
f1
0
0
0
1
f2
0
0
1
0
f3
0
0
1
1
f4
0
1
0
0
f5
0
1
0
1
f6
0
1
1
0
f7
0
1
1
1
f8
1
0
0
0
f9 f10 f11 f12 f13 f14 f15
1 1 1 1 1 1 1
0 0 0 1 1 1 1
0 1 1 0 0 1 1
1 0 1 0 1 0 1
Die Funktionen f0 bis f15 tragen ihrer Bedeutung nach folgende Namen:
Funktion
f0
f1
f2
f3
f4
f5
f6
f7
f8
f9
f10
f11
f12
f13
f14
f15
Bezeichnung
NULL
AND
x→y
Projektion auf x
y→x
Projektion auf y
XOR
OR
NOR
EQUIV
Projektion auf ȳ
y→x
Projektion auf x̄
x→y
NAND
EINS
Eine 4-stellige Schaltfunktion sei durch die folgende Funktionstabelle gegeben.
x3
0
0
0
0
1
x2
0
1
1
1
0
x1
0
0
1
1
1
x0
0
1
0
1
1
f
1
0
0
1
0
Mit | D |= 5 gibt es genau 25 = 32 Schaltfunktionen f0 , . . . , f31 .
4.1.2
Atom, Minterm und Maxterm
In diesem Abschnitt betrachten wir kleinste und größte Schaltfunktionen.
4.1. Schaltfunktionen, Bausteinsysteme und Boolesche Algebra
Definition: Atom einer Booleschen Algebra
a ∈ A mit a 6= 0 heißt Atom einer Booleschen Algebra (A, ·, +, ¯ ) genau dann, wenn a · b =
a oder a · b = 0, für alle b ∈ A (a · b 6= 0 ⇒ a · b = a)
Atome einer Booleschen Algebra sind die kleinsten Elemente, die multipliziert mit
einem anderen Element entweder das Element selbst oder Null ergeben. In Mengenalgebren ℘(A) sind die Atome gerade die einelementigen Mengen mit ∩.
Definition: Minterm
Ein Minterm ist eine atomare Schaltfunktion, die an genau einer Stelle 1 ist.
Hat eine Schaltfunktion in ihrer Funktionstabelle genau eine 1, so ist sie ein Minterm:
xn−1 . . . x0
0...0
..
.
..
.
εn−1 . . . ε0
..
.
..
.
1...1
f
0
..
.
0
1
0
..
.
0
Die Schaltfunktion f hat dann die Form:
f=
x0ε0
· x1ε1
εn−1
,
· . . . · xn−1
wobei
xiεi
(
xi
=
x̄i
wenn εi = 1
wenn εi = 0
55
56
Kapitel 4. Bausteine und Komponenten von Rechensystemen
Beispiel: Minterm
Sei die Funktion f4 durch folgende Funktionstabelle gegeben.
x1
0
0
1
1
x0
0
1
0
1
f4
0
1
0
0
Dann ist x̄1 · x0 ein Minterm.
Ein zum Minterm dualer Begriff ist der des Maxterms, also der größten Schaltfunktion ungleich der 1-Funktion.
Definition: Maxterm
Ein Maxterm ist eine atomare Schaltfunktion, die an genau einer Stelle 0 ist.
Eine Schaltfunktion, die in ihrer Funktionstabelle genau eine 0 enthält, ist ein Maxterm:
xn−1 . . . x0
0...0
..
.
..
.
εn−1 . . . ε0
..
.
f
1
..
.
1...1
1
1
0
1
..
.
Die Schaltfunktion f hat dann die Form:
f=
x0ε̄0
+ x1ε̄1
ε̄n−1
,
+ . . . + xn−1
wobei
¯
xiεi
(
x̄i
=
xi
wenn εi = 1
wenn εi = 0
Minterme und Maxterme ermöglichen standardisierte Darstellungen von Schaltfunktionen, so genannte Normalformen, welche im nächsten Abschnitt vorgestellt werden.
4.1.3
Boolesche Ausdrücke
Bisher wurden Schaltfunktionen über Funktionstabellen mit Eingängen (x0 , . . . , xn−1 )
und Ausgang f (x0 , . . . , xn−1 ) definiert. Jetzt werden x0 , . . . , xn−1 und f als Variablen interpretiert. Wir gehen also von Schaltfunktionen mit Eingängen x0 , . . . , xn−1
zu Booleschen Funktionen in x0 , . . . , xn−1 über. Da Schaltfunktionen eine Boolesche
Algebra bilden, dürfen wir Boolesche Ausdrücke mit den Rechenregeln der Booleschen Algebra umformen.
4.1. Schaltfunktionen, Bausteinsysteme und Boolesche Algebra
Definition: Boolescher Ausdruck
Sei X = {0, 1, x0 , . . . , xn−1 } eine Menge von Booleschen Variablen mit den Atomen 0 und
1.
Die Boolesche Ausdrücke k-ter Stufe über X sind dann induktiv wie folgt definiert:
Stufe 0 :
Elemente von X
Stufe (k + 1) : (w0 · w1 · . . . · wr−1 ),
(w0 + w1 + . . . + wr−1 ) oder
w̄,
wobei w, wi Boolesche Ausdrücke sind mit maxi (Stufe(wi )) = k und Stufe(w) = k.
Hierbei ist die Stufenzahl gleich der Klammertiefe und gleich der Anzahl hintereinander zu durchlaufender AND-, OR- und NOT-Schaltungen.
Zusammenhang zwischen Booleschen Ausdrücken und Schaltfunktionen
Der Zusammenhang zwischen Booleschen Ausdrücken und Schaltfunktionen wird
durch die folgenden Aussagen beschrieben.
a) Jedem Booleschen Ausdruck entspricht eindeutig eine Schaltfunktion
Sei B(X) = {Boolesche Ausdrücke über X = {x0 , . . . , xn−1 }},
S(Bn ) ={Schaltfunktionen f : Bn → B} und ϕ : B(X) → S(Bn ) eine Abbildung,
die wie folgt induktiv definiert ist:
ϕ(0)
ϕ(1)
ϕ(xi )
ϕ((w1 ·w2 ))
ϕ((w1 + w2 ))
ϕ((w̄))
=
=
=
=
=
=
NULL
EINS
xi
AND(ϕ(w1 ), ϕ(w2 ))
OR(ϕ(w1 ), ϕ(w2 ))
NOT(ϕ(w))
NULL ist eine Schaltfunktion: 0
EINS ist eine Schaltfunktion: 1
Projektion auf i-te Komponente
Die Funktionstabelle eines Booleschen Ausdrucks ist eindeutig. Umgekehrt gilt
dies aber nicht.
b) Zu jeder Schaltfunktion gibt es unendlich viele Boolesche Ausdrücke
Zwei Boolesche Ausdrücke heißen äquivalent, wenn sie dieselbe Schaltfunktion
definieren. Seien a, b ∈ B(X) Boolesche Ausdrücke, a ist äquivalent zu b (a ≡ b)
genau dann, wenn ϕ(a) = ϕ(b).
Man sieht sofort: a äquivalent b, sofern a in b mit Hilfe der Rechenregeln der
Booleschen Algebra umwandelbar ist.
Beispiel: Umformungen
≡
≡
≡
≡
≡
≡
x̄1 · x2 + x1 · x̄2 + x1 · x2
x̄1 · x2 + x1 · x̄2 + x1 · x2 + x1 · x2
x̄1 · x2 + x1 · x2 + x1 · x̄2 + x1 · x2
(x̄1 + x1 ) · x2 + x1 · (x̄2 + x2 )
1 · x2 + x1 · 1
x2 + x1
x1 + x2
wegen a ≡ a + a
wegen (K)
wegen (D)
wegen a + ā = 1
wegen (K) und a · 1 = a
wegen (K)
57
58
Kapitel 4. Bausteine und Komponenten von Rechensystemen
Hierbei sind alle Booleschen Ausdrücke äquivalent. Außerdem handelt es sich
bei dem letzten Ausdruck offenbar um einen besonders einfachen und billig zu
realisierenden Booleschen Ausdruck.
c) Aus der Menge der Booleschen Ausdrücke kann man einen suchen, der die Schaltfunktion am billigsten bzw. am schnellsten realisiert.
Um einen Booleschen Ausdruck zu finden, der dem ersten Kriterium genügt, ist
es erforderlich ein Kostenmaß zu definieren, das eine Entscheidung erlaubt. Um
das zweite Kriterium zu benutzen muss man analog ein Zeitmaß einführen.
Ergänzung für unvollständig definierte Schaltfunktionen
Ist eine n-stellige Schaltfunktion nicht auf dem gesamten Bereich definiert, d.h. f :
Bn ⊃ D → B, Bn \D 6= ∅, wenn also Don’t Care-Bedingungen vorliegen, dann heißen zwei Boolesche Ausdrücke äquivalent, wenn sie auf D dieselbe Schaltfunktion
realisieren.
Don’t Cares sind beliebig besetzbar, das heißt, man darf Minterme, die sich nur
auf Bn \D beziehen (also auf D die Nullfunktion liefern), beliebig hinzufügen oder
weglassen.
Zwei Boolesche Ausdrücke liefern dieselbe Schaltfunktion f : D → B genau dann,
wenn sie ineinander überführbar sind.
Beispiel: Schaltfunkion vs. Boolescher Ausdruck
Sei eine Schaltfunktion durch folgende Funktionstabelle gegeben:
x2
0
0
0
0
1
1
1
1
x1
0
0
1
1
0
0
1
1
x0
0
1
0
1
0
1
0
1
f
0
0
0
1
1
1
Don’t Care
Don’t Care
Ein Boolescher Ausdruck für f ist zum Beispiel:
x̄2 x1 x0 + x2 x̄1 x̄0 + x2 x̄1 x0
Durch Umformungen erhält man einen einfacheren Ausdruck:
4.2. Normalformen
59
≡ x̄2 x1 x0 + x2 x̄1 x̄0 + x2 x̄1 x0 + x2 x1 x̄0 + x2 x1 x0
Don’t Cares hinzufügen, sie werden mit 1 besetzt
≡ x̄2 x1 x0 + x2 (x̄1 x̄0 + x̄1 x0 + x1 x̄0 + x1 x0 )
≡ x̄2 x1 x0 + x2
≡ x̄2 x1 x0 + x2 + x2 x1 x0
Don’t Care hinzufügen
≡ (x̄2 + x2 )x1 x0 + x2
≡ x1 x0 + x2
Im Beispiel werden Don’t Cares hinzugefügt. Es kann auch sinnvoll sein, sie wegzulassen. Trivialbeispiel: NULL : D → B, hier wäre es sinnlos, Don’t Cares auf 1 zu
setzen.
4.2 Normalformen
In diesem Abschnitt werden standardisierte Darstellungen von Schaltfunktionen durch
Boolesche Ausdrücke eingeführt, die aus einer Funktionstabelle systematisch hergeleitet werden können.
4.2.1
Disjunktive Normalform (DNF)
Hier wird ein Boolescher Ausdruck zu einer Schaltfunktion als Vereinigung der Minterme dargestellt.
Definition: Einschlägiger Index
Die Zeilennummer ε einer Funktionstabelle zu einer Schaltfunktion f heißt einschlägiger
Index zu f : Bn → B, falls f (ε0 , . . . , εn−1 ) = 1 ist.
Definition: ε-ter Minterm
Sei ε ein Index von f . Dann heißt die Funktion mε : Bn → B, definiert durch
ε
ε
n−1
mε (x0 , . . . , xn−1 ) = x00 · x1ε1 · . . . · xn−1
ε-ter Minterm von f .
Dabei sei
ε
xjj
(
xj
=
x¯j
falls ε j = 1
falls ε j = 0
60
Kapitel 4. Bausteine und Komponenten von Rechensystemen
Definition: Disjunktive Normalform (DNF)
Sei I die Menge der einschlägigen Indizes zu einer Schaltfunktion f . Die Disjunktive
Normalform zu f ist dann definiert als Disjunktion von Mintermen
[m
ε
ε∈I
4.2.2
Konjunktive Normalform (KNF)
Definition: ε-ter Maxterm
Sei ε Index von f : Bn → B, und sei mε der ε-te Minterm von f . Dann heißt die Funktion
Mε : Bn → B definiert durch
Mε (x0 , . . . , xn−1 ) = mε (x0 , x1 , . . . , xn−1 )
ε-ter Maxterm von f . Kurz schreibt man Mε = mε
Eine Schaltfunktion wird als Durchschnitt der Maxterme dargestellt. Sie lässt sich
aus der DNF herleiten.
Aus
NF( f ) =
[
ε
{ε| f (ε)=1}
folgt
NF( f¯) =
[
{ε| f (ε)=0}
ε
n−1
x0ε0 · x1ε1 · . . . · xn−1
=
n−1
x0ε0 · x1ε1 · . . . · xn−1
∏
{ε| f (ε)=0}
ε̄
n−1
x0ε̄0 ∪ x1ε̄1 ∪ . . . ∪ xn−1
De Morgan
Somit ergibt sich die konjunktive Normalform für f :
NF( f ) =
∏
{ε| f (ε)=0}
ε̄
n−1
x0ε̄0 ∪ x1ε̄1 ∪ . . . ∪ xn−1
Definition: Konjunktive Normalform (KNF)
Sei J = {ε | f (ε) = 0} eine Menge von Indizes zu einer Schaltfunktion f . Die Konjunktive
Normalform zu f ist dann definiert als
ε̄n−1
ε̄
KNF( f ) = ∏ x00 ∪ x1ε̄1 ∪ . . . ∪ xn−1
{ε∈J}
Wenn f nur auf D definiert ist, betrachtet man nur die Produkt- bzw. Vereinigungsbildung
bezüglich D.
4.2.3
Komplementfreie Ringsummenentwicklung (KRE)
Aus der vollständigen disjunktiven Normalform lässt sich eine weitere Normalform
herleiten, die aus ⊕, · und 1 besteht. Dabei stellt ⊕ das Symbol für das Exklusive-Or
4.2. Normalformen
61
dar. 1 ist eine Basisfunktion. Eine Schaltfunktion f hat dann die Darstellung:
KRE( f ) = a0 ⊕ a1 · x1 ⊕ . . . ⊕ an · xn ⊕
an+1 · x1 · x2 ⊕ an+2 · x1 · x3 ⊕ . . .
..
.
a2n −1 · x1 · . . . · xn
mit ai ∈ {0, 1}
n
Es gibt somit 2n Disjunktionsglieder. Ferner gibt es 22 verschiedene Schaltfunktionen, da ai entweder mit 0 oder 1 belegt ist. Liegt die disjunktive Normalform einer
Schaltfunktion f vor, so erhält man nach folgender Vorgehensweise die KRE( f ) :
a) Ersetze in DNF ∪ durch ⊕.
Dies ist erlaubt, da Minterme a, b die Bedingung a · b = 0 für a 6= b erfüllen.
b) Ersetze x̄i durch (1 ⊕ xi )
c) Ausmultiplizieren
d) Zusammenfassen a ⊕ a = 0; a · a = a
Das Ergebnis ist eindeutig bestimmt und von der oben angegebenen Form. Zum Umgang mit dem exklusiven Oder ⊕ seien folgende Rechenregeln angegeben:
• x ⊕ 1 = x̄, x ⊕ 0 = x
• x ⊕ x = 0, x ⊕ x̄ = 1
• x⊕y = y⊕x
• x ⊕ (y ⊕ z) = (x ⊕ y) ⊕ z
• x · (y ⊕ z) = x · y ⊕ x · z
• 0⊕0⊕...⊕0 = 0
(
1 wenn n ungerade
• 1⊕1⊕...⊕1 =
0 wenn n gerade
n ist dabei die Anzahl der Einsen.
Beispiel: Normalformen DNF, KNF und KRE
Zum Abschluss dieses Abschnitts werden die drei Normalformen durch ein Beispiel illustriert. Sei hierzu die Schaltfunktion durch folgende Funktionstabelle gegeben:
62
Kapitel 4. Bausteine und Komponenten von Rechensystemen
x2
0
0
0
0
1
1
1
1
x1
0
0
1
1
0
0
1
1
x0
0
1
0
1
0
1
0
1
f
0
1
0
0
0
1
0
1
Disjunktive Normalform
Minterme zu den einschlägigen Indizes sind:
m1 (x2 , x1 , x0 ) = x̄2 · x̄1 · x0
m5 (x2 , x1 , x0 ) = x2 · x̄1 · x0
m7 (x2 , x1 , x0 ) = x2 · x1 · x0
⇒ DNF( f ) = x̄2 · x̄1 · x0 + x2 · x̄1 · x0 + x2 · x1 · x0
Konjunktive Normalform
KNF( f ) = (x2 + x1 + x0 ) · (x2 + x̄1 + x0 ) · (x2 + x̄1 + x̄0 ) · (x̄2 + x1 + x0 ) · (x̄2 + x̄1 + x0 )
Komplementfreie Ringsummenentwicklung
KRE( f ) = x̄2 · x̄1 · x0 ⊕ x2 · x̄1 · x0 ⊕ x2 · x1 · x0
= (1 ⊕ x2 ) · (1 ⊕ x1 ) · x0 ⊕ x2 · (1 ⊕ x1 ) · x0 ⊕ x2 · x1 · x0
= x2 ⊕ x1 · x0 ⊕ x2 · x0 ⊕ x2 · x1 · x0 ⊕ x2 · x0 ⊕ x2 · x1 · x0 ⊕ x2 · x1 · x0
= x0 ⊕ x1 · x0 ⊕ x2 · x1 · x0
Es gilt: ϕ(DNF( f )) = ϕ(KNF( f )) = ϕ(KRE( f ))
4.3 Synthese von Schaltkreisen, Minimierung
Für jede Schaltfunktion gibt es unendlich viele Boolesche Ausdrücke und damit
unendlich viele Schaltkreise, welche sie realisieren.
Beispiel: Darstellung von Schaltfunktionen
x¯1 · x2 + x1 · x¯2 + x1 · x2 und x1 + x2 sind Ausdrücke für dieselbe Schaltfunktion OR.
Um den einfachsten und billigsten Booleschen Ausdruck und den ihn realisierenden
Schaltkreis (bzgl. AND, OR und NOT ) zu finden, muss man ein Kostenmaß definieren.
Wir setzen dazu (sehr vereinfachend): Kosten Boolescher Ausdrücke = Anzahl der
Eingänge in AND- beziehungsweise OR-Gatter des entsprechenden Schaltkreises.
Die Negationen, Überkreuzungen, Leitungsduplikationen, Leitungslängen, Ausgän-
4.3. Synthese von Schaltkreisen, Minimierung
63
ge, Gatter usw. bleiben unberücksichtigt.
Definition: Kostenfunktion
Eine Kostenfunktion k : B(X) → N0 sei definiert durch:
• k(xi ) = k(0) = k(1) = 0 (Leitungen sind kostenlos)
• k(w0 + . . . + wr−1 ) = k(w0 · . . . · wr−1 ) = ∑r−1
i=0 k(wi ) + r
r = Anzahl der Eingänge in das Gatter dieser Stufe
• k(w̄) = k(w) (Negation ist kostenlos)
Nach dieser Definition kostet eine Konjunktion (AND) beziehungsweise Disjunktion (OR)
mit r Eingängen r Einheiten zuzüglich der Kosten vorgeschalteter Schaltkreise (Gatter).
Beispiel: Kosten von Schaltfunktionen
k(x1 · (x2 + x3 ) · x4 + x1 ) = k(x1 · (x2 + x3 ) · x4 ) + k(x1 ) + 2
= k(x1 ) + k((x2 + x3 )) + k(x4 ) + 3 + k(x1 ) + 2
= k(x1 ) + k(x2 ) + k(x3 ) + 2 + k(x4 ) + 3 + k(x1 ) + 2
= 0+0+0+2+0+3+0+2
= 7
Wie oben schon erwähnt gibt es zu einer Schaltfunktion unendlich viele Boolesche
Ausdrücke a0 , a1 , . . . mit ϕ(ai ) = f . Das Allgemeine Minimierungsproblem besteht
darin einen Ausdruck a∗ ∈ ϕ−1 ( f ) mit den geringsten Kosten bezüglich obiger Definition: k(a∗ ) ≤ k(b) für alle b ∈ ϕ−1 ( f ) zu finden. Dieses Problem ist bisher jedoch
ungelöst. Deshalb wird im nächsten Abschnitt eine eingeschränkte Variante mit Lösungsansätzen vorgestellt.
4.3.1
Eingeschränktes Minimierungsproblem
Das Ziel beim eingeschränkten Minimierungsproblem ist die Bestimmung einer billigsten zweistufigen Realisierung, das heißt, eine Realisierung, bei der nur maximal
zwei AND- bzw. OR-Gatter hintereinander durchlaufen werden. Die konjunktive und
die disjunktive Normalform gehören zu diesen zweistufigen Realisierungen.
Im Folgenden beschränken wir uns auf zweistufige Realisierungen, welche aus der
disjunktiven Normalform ableitbar sind. Hierbei wird erst ein AND- und dann ein
OR-Gatter durchlaufen. Solche Realisierungen heißen Polynome.
Definition: Minimalpolynom
P(X) ist die Menge der polynomialen Booleschen Ausdrücke über den Booleschen Variablen X = {x0 , . . . , xr−1 } :
εi
εi
r−1
}
P(X) = {p | p = a0 + . . . + am−1 ; p = 1; p = 0 mit ai = xi00 · . . . · xir−1
64
Kapitel 4. Bausteine und Komponenten von Rechensystemen
ai heißt Monom.
Ein billigstes Polynom zur Realisierung von f heißt Minimalpolynom von f .
Ein Monom a heißt Implikant von f genau dann, wenn ϕ(a) ≤ f (≤-komponentenweise)
Beispiel: Minimalpolynom
Sei die Schaltfunktion f durch die folgende Funktionstabelle gegeben.
x2
0
0
0
0
1
1
1
1
x1
0
0
1
1
0
0
1
1
x0
0
1
0
1
0
1
0
1
f
0
0
1
1
1
0
1
0
ϕ(a1 )
0
0
0
0
1
0
1
0
ϕ(a2 )
0
0
0
0
0
1
0
0
Aus der Funktionstabelle folgt:
a1 = x2 x̄1 x̄0 + x2 x1 x̄0 = x2 x̄0 und a2 = x2 x̄1 x0
a1 ist Implikant von f ; a2 nicht, da ϕ(a2 (1, 0, 1)) = 1 0 = ϕ( f (1, 0, 1)).
Alle Minterme zu den einschlägigen Indizes einer Schaltfunktion sind auch Implikanten derselben. Kürzere Implikanten überdecken mehr Einsen von f und sind
billiger als längere. Da ein Polynom von f gerade eine Überdeckung von f durch
Implikanten ist, werden für eine billige Realisierung kürzeste Implikanten gesucht.
Definition: Primimplikant
a heißt Primimplikant von f genau dann, wenn a Implikant von f und kein Teilmonom
von a Implikant ist.
Beispiel: Implikanten von Schaltfunktionen
Seien x · α · y und x · ᾱ · y Implikanten von f . Es gilt also:
ϕ(x · α · y) ≤ f und ϕ(x · ᾱ · y) ≤ f
Dann erhält man einen minimalen Implikanten von f :
⇒ ϕ(x · α · y + x · ᾱ · y)
⇒ ϕ(x · (α + ᾱ) · y)
⇒ ϕ(x · y)
4.3.2
≤
≤
≤
f
f
f
Kosten: 2 · (k(x) + k(y) + k(α)) + 8
Kosten: k(x) + k(y) + 2
Quine-McCluskey-Algorithmus
Es wird nun ein Algorithmus vorgestellt, der eine Lösung des eingeschränkten Minimierungsproblems ist. Der Algorithmus besteht aus zwei Phasen.
Phase a) Bestimme alle Primimplikanten von f .
4.3. Synthese von Schaltkreisen, Minimierung
65
Phase b) Setze hieraus eine billigste Überdeckung von f zusammen, das heißt, suche eine billigste Gesamtüberdeckung der Minterme (ohne jene, die durch
Don’t Cares entstanden sind) durch geschickte Auswahl einer Menge von Primimplikanten.
Phase a): Prinzip zum Auffinden von Primimplikanten
Starte mit Mintermen und Don’t Cares von f . Nutze dabei die Nachbarschaftsbeziehung – wie oben gezeigt x · y = x · α · y + x · ᾱ · y – so oft wie möglich aus. Dieses
Verfahren liefert alle Primimplikanten.
Zur Systematik:
1. Ersetze xiεi durch εi und ergänze fehlende Variablen durch „–“ an der entsprechenden Stelle.
x̄5 x3 x̄0 entspricht „0 − −1 − 0“.
2. Nachbarn sind nur in Monomen möglich, die sich bezüglich ihres Gewichts, d.h.
der Anzahl der enthaltenen Einsen, um genau Eins unterscheiden. Daher sollte
man die Monome nach dem Gewicht vorsortieren. Dazu kann z.B. das HammingGewicht eines binären Vektors vi genutzt werden:
n
Weight = w(v) = ∑ vi
i=1
Phase b): Überdeckung von f aus Primimplikanten
1. Man erstellt eine Matrix mit
• Primimplikanten p j als Zeilen und
• Mintermen mi der DNF (ohne Don’t Cares) als Spalten.
p1
p2
p3
..
.
m1 m2 m3 . . .
1
1
1
1
Der Matrixeintrag a jr = 1 genau dann, wenn der Primimplikant p j den Minterm
mr überdeckt, d.h. der Minterm stimmt in allen Komponenten mit dem Primimplikanten überein. An Stellen, wo der Primimplikant ein − hat, kann im Minterm
an gleicher Stelle beliebiges (1 oder 0) stehen.
66
Kapitel 4. Bausteine und Komponenten von Rechensystemen
Beispiel: Überdeckungsmatrix
1 − 1− überdeckt 1110, 1010, 1011 und 1111.
00− überdeckt nicht 1011, denn es muss gelten: ϕ(ā · b̄) ≥ ϕ(a · b̄ · c · d).
Mit a = 1, b = 0, c = 1 und d = 1 ist die „rechte Seite“, aber nicht die „linke Seite“
erfüllt.
2. Ein Primimplikant heißt wesentlich genau dann, wenn es einen Minterm mi gibt,
der nur von diesem Primimplikanten überdeckt wird. In der entsprechenden Matrixspalte befindet sich nur eine 1. Ein wesentlicher Primimplikant muss zum Minimalpolynom gehören, er ist unverzichtbar. Alle zusätzlich überdeckten Minterme der Matrix sind zu streichen, weil sie schon überdeckt sind.
3. Ist ϕ(mi ) ≤ ϕ(m j ), so streiche m j , denn jede Überdeckung von mi liefert m j mit.
p1
p2
p3
p4
..
.
. . . mi . . . m j
1
1
1
...
1
1
4. Ist ϕ(pr ) ≤ ϕ(ps ), wörtlich ps leistet mehr als pr , und k(pr ) ≥ k(ps ), so streiche
pr , denn ps ist billiger und leistungsfähiger.
m1 m2 m3 . . .
..
.
pr
..
.
ps
..
.
1
1
1
1
1
Mit den Schritten 2, 3 und 4 (evtl. iteriert) wird die Bestimmung einer Überdeckung
oft ein eindeutig bestimmter Vorgang. Manchmal müssen aber mehrere Möglichkeiten geprüft und eine insgesamt billigste Lösung ausgewählt werden.
Beispiel: Gray-Code-Addierer
In diesem Beispiel sollen Boolesche Ausdrücke für die Realisierung eines Addierers zweistelliger Gray-Code-Zahlen x1 x0 und y1 y0 mittels Quine-McCluskey-Algorithmus bestimmt werden.
4.3. Synthese von Schaltkreisen, Minimierung
y1
y0
c
67
x1
z1
x0
z0
Die Schaltfunktion sei durch folgende Funktionstabelle gegeben:
x1
0
0
0
0
0
0
0
0
1
1
1
1
1
1
1
1
x0
0
0
0
0
1
1
1
1
1
1
1
1
0
0
0
0
y1
0
0
1
1
0
0
1
1
0
0
1
1
0
0
1
1
y0
0
1
1
0
0
1
1
0
0
1
1
0
0
1
1
0
c
0
0
0
0
0
0
0
1
0
0
1
1
0
1
1
1
z1
0
0
1
1
0
1
1
1
1
1
1
1
1
1
1
0
z0
0
1
1
0
1
1
0
0
1
0
0
1
0
0
1
1
Schaltfunktion und Minimalpolynom für c:
Sei In die Tabelle der Implikanten der Länge n, wobei sich die Länge aus der Anzahl an
0-en und 1-en ergibt. Die Minterme sind in der Tabelle zeilenweise nach Gewicht sortiert.
I4
1001
1010
0110
1011
1110
1111
I3
10 − 1
101−
1 − 10
−110
1 − 11
111−
I2
1 − 1−
Man vergleiche jeden Minterm einer Gewichtsgruppe mit jedem der darunter befindlichen
Gruppe. Falls sich diese an genau einer Stelle unterscheiden, so schreibe man an diese Stelle
einen −: 1001 und 1011 aus I4 führen zu 10 − 1 in I3 . Befinden sich in den Mintermen −,
so müssen diese an den gleichen Stellen auftreten: 1 − 10 und 1 − 11 aus I3 ergibt 1 − 1− in
I2 . Als Primimplikanten erhält man diejenigen Implikanten, welche nicht weiter reduziert
werden können, hier: 10 − 1, −110 aus I3 und 1 − 1− aus I2 .
68
Kapitel 4. Bausteine und Komponenten von Rechensystemen
Die Überdeckungsmatrix lautet:
10 − 1
−110
1 − 1−
1001
1
1010
0110
1011
1
1
1
1
1110
1111
1
1
1
Wie man erkennt, sind alle Primimplikanten wesentlich. Das Minimalpolynom ist also:
MPc = x1 · y1 + x1 · x̄0 · y0 + x0 · y1 · ȳ0
Schaltfunktion und Minimalpolynom für z1 :
Zunächst die Primimplikanten ermitteln:
I4
I3
I2
0010 001− 0 − 1−
1000 0 − 10 1 − 0−
1 − 00
100−
1100 110− 11 − −
0101 11 − 0 −1 − 1
1001 −101 1 − −1
0011 01 − 1 − − 11
0110 1 − 01 −11−
10 − 1
0 − 11
−011
011−
−110
1101 11 − 1
0111 −111
1011 1 − 11
1110 111−
1111
Überdeckungsmatrix:
0010 1000 1100 0101 1001 0110 0011 1011 1101 0111 1110 1111
0 − 1− 1
1
1
1
1 − 0−
1
1
1
1
11 − −
1
1
1
1
−1 − 1
1
1
1
1
1 − −1
1
1
1
1
− − 11
1
1
1
1
−11−
1
1
1
1
Wesentliche Primimplikanten sind: 0 − 1−, 1 − 0− und −1 − 1. Sie überdecken alle Minterme bis auf 1011 und 1110. Nach Streichen der bisher überdeckten Minterme bleibt:
4.3. Synthese von Schaltkreisen, Minimierung
1011
11 − −
1 − −1
− − 11
−11−
69
1110
1
1
1
1
Jede Überdeckung benutzt zwei Primimplikanten und ist gleich teuer, so dass die Wahl
beliebig ist.
Das Minimalpolynom hat die Form:
MPz1 = x̄1 · y1 + x1 · ȳ1 + x0 · y0 +Y
mit Y ∈ {x1 · x0 + x1 · y0 , x1 · x0 + y1 · y0 , x0 · y1 + x1 · y0 , x0 · y1 + y1 · y0 }
Schaltfunktion und Minimalpolynom für z0 :
Die Primimplikanten ergeben sich durch folgende Tabelle:
I4
0100
0001
0101
0011
1100
1010
1011
1110
I3
010−
−100
0 − 01
00 − 1
11 − 0
101−
1 − 10
−011
Alle Implikanten der letzten Spalte sind Primimplikanten.
Überdeckungsmatrix:
010−
−100
0 − 01
00 − 1
11 − 0
101−
1 − 10
−011
0100
1
1
0001
0101
1
1
1
1
0011
1100
1010
1011
1
1
1
1110
1
1
1
1
1
1
1
In jeder Spalte stehen zwei, d.h. mehr als eine, Einsen, also liegt kein wesentlicher Primimplikant vor. Da kein Primimplikant wesentlich ist (alle gleich teuer), beginnen wir mit
010−:
70
Kapitel 4. Bausteine und Komponenten von Rechensystemen
010−
−100
0 − 01
00 − 1
11 − 0
101−
1 − 10
−011
0100
1
1
0001
0101
1
1
1
1
0011
1100
1010
1011
1
1
1
1110
1
1
1
1
1
1
1
Von 101−, 1 − 10 und −011 wählt man 101−, weil dieser Primimplikant 1010 und 1011
überdeckt und diejenigen Minterme, welche 1 − 10 und −011 überdecken, bereits abgedeckt sind. Wesentliche Primimplikanten sind somit: 010−, 00 − 1, 11 − 0 und 101−. Ausgehend von 010− (entspricht x0 ) ergibt sich folgendes eindeutiges Minimalpolynom:
MPz0 = x̄1 · x0 · ȳ1 + x̄0 · x̄0 · y0 + x1 · x0 · ȳ0 + x1 · x̄0 · y1
Beginnt man mit −100 statt mit 010−, dann entsteht in eindeutiger Weise:
MPz0 = x0 · ȳ1 · ȳ0 + x̄1 · ȳ1 · y0 + x̄0 · y1 · y0 + x1 · y1 · ȳ0
Beide Minimalpolynome sind gleich teuer.
4.3.3
Karnaugh-Diagramme
Ein Karnaugh-Diagramm (siehe Abbildung 4.1) einer Booleschen Funktion f : Bn →
B mit n ∈ {3, 4} ist eine graphische Darstellung der Funktionstabelle von f durch
eine Matrix der Größe 2 × 4 für n = 3 bzw. 4 × 4 für n = 4, deren Spalten mit den
möglichen Belegungen der Variablen x0 und x1 und deren Zeilen mit den Belegungen
der Variablen x2 (n = 3) bzw. x2 und x3 (n = 4) beschriftet sind. Die Reihenfolge
der Beschriftung erfolgt so, dass sich zwei zyklisch benachbarte Zeilen/Spalten nur
in genau einer Komponente unterscheiden (Gray-Code).
x1x0
00
x2
01
11
10
x1x0
x3x2 00
0
00
1
01
01
11
10
Abbildung 4.1: Karnaugh-Diagramme
11
10
4.4. Schaltwerke und Speicherelemente
71
Vorgehen zur Bestimmung eines Minimalpolynoms
• An den Matrixelementen, deren Beschriftung ein einschlägiger Index für die
Funktion f ist, eine 1 eintragen.
• Maximale 1-er-Blöcke der Form 2s × 2r finden, so dass jede 1 mindestens einmal überdeckt ist. Dabei müssen auch zyklische Überdeckungen beachtet werden.
• Summe über den Termen, die den Blöcken entsprechen, bilden.
• Falls möglich, zusätzlich Don’t Cares ausnutzen, indem im ersten Schritt in
den entsprechenden Feldern auch der Wert 1 zugeordnet wird. Damit sind mehr
Einsen vorhanden und evtl. größere Resolutionsblöcke möglich. Don’t Cares
brauchen allerdings nicht vollständig überdeckt zu werden.
Beispiel: Karnaugh-Diagramm
x1x0
00
x2
01
11
1
0
1
1
D
10
x1x0
x3x2 00
00
D
01
1
01
10
10
1
1
11
1
11
x2x0
1
1
1
x1x0
D
x2x1x0
1
D
x2x1
f1 = x1x0 + x2x1
f2 = x2x0 + x2x1x0
4.4 Schaltwerke und Speicherelemente
Die bisherigen Betrachtungen waren weitgehend theoretischer Natur. Für die Realisierung von Schaltfunktionen wurde der Begriff des Booleschen Ausdrucks eingeführt sowie eine Minimierung dessen bezüglich einer einfachen Kostenfunktion. Des
Weiteren wurden Schaltkreise betrachtet, wobei die Zeit außerhalb der Betrachtung
blieb. In diesem Abschnitt wird eine Taktung eingeführt, um die Schaltfunktion in
ihrer Realisierung als Schaltwerk zu diskreten Zeitpunkten auf die Eingangsargumente anzuwenden.
72
Kapitel 4. Bausteine und Komponenten von Rechensystemen
Definition: Schaltkreis und Schaltwerk
Schaltkreise bestehen aus Eingangsleitungen, Schaltnetz und Ausgangsleitungen. Schaltwerke bestehen aus Schaltkreisen, Speicherelementen und Taktleitungen (siehe Abbildung 4.2)
Takt
sonstige
Eingangsleitungen
Speicherelemente
Schaltkreise
sonstige
Ausgangsleitungen
Abbildung 4.2: Schaltkreis und Schaltwerk
Schaltwerke befinden sich zu gegebener Zeit in einem Zustand Q. Ein solcher Zustand ist etwa durch die Werte der Ausgangsleitungen zu diesem Zeitpunkt charakterisiert. Zustände ändern sich nur zu bestimmten diskreten Zeitpunkten, bei Eintreffen
eines Taktes (siehe Abbildung 4.3), das heißt, wenn eine 1 auf der Taktleitung anliegt.
T
Flanke
T=1
1
T=0
Zeit
0
Abbildung 4.3: Takt
4.4.1
Speicherelemente
Binäre Speicherelemente sind kleinste logische Bausteine zur Aufbewahrung (Speicherung) einer Information. Es wird hier nur einer der Zustände 0 oder 1 gespeichert.
Sie sind als Schaltwerke realisiert. Dabei ist ein Zustand Q(n) durch den gespeicherten
Wert und durch die Werte auf den Ausgangsleitungen im n-ten Taktzyklus bestimmt.
4.4. Schaltwerke und Speicherelemente
73
Der gespeicherte Wert steht über eine Ausgangsleitung zur Verfügung; meist gibt es
eine zusätzliche Leitung, an der Qn anliegt.
RS-Flipflop
Dieses Speicherelement besitzt zwei besondere Eingänge zum Setzen (auf 1; Set) und
Rücksetzen (auf 0; Reset) des Inhalts (siehe Abbildung 4.4). Der Name Flipflop rührt
von der Geräuschentwicklung der ersten Relais-Schaltwerke her, die zur Realisierung
von Speicherelementen verwendet wurden.
R
Q(n)
S
T
Q(n+1)
Abbildung 4.4: RS-Flipflop
Sei das RS-Flipflop durch folgende Funktionstabelle beschrieben.
R
0
0
1
1
S
Qn+1
0
Qn
1
1
0
0
1 Don’t Care
Sei T der Takt mit den beiden Zuständen:
T
0
1
Auswirkung
Zustand ändert sich nicht
Zustand kann sich ändern
Unter Einbeziehung des jeweils aktuellen Zustandes Q(n) ergibt sich folgende Tabelle
für die Schaltfunktion von Q(n+1) , wenn ein Takt anliegt (T = 1), sonst (T = 0) ändert
sich nichts:
74
Kapitel 4. Bausteine und Komponenten von Rechensystemen
S Qn
Qn+1
0 0
0
0 1
1
1 0
1
1 1
1
0 0
0
0 1
0
1 0 Don’t Care
1 1 Don’t Care
R
0
0
0
0
1
1
1
1
Die Schaltfunktion für Q(n+1) ergibt sich zu
Q(n+1) = T̄ · Q(n) + T · (S + R̄ · Q(n) )
= T̄ · Q
(n)
(n)
+ T · S + T · R̄ · Q
= T̄ · Q(n) + T · S + R̄ · Q(n)
(Torschaltung, if T = 0 then . . . else . . . )
+ T̄ · R̄ · Q(n)
= (T̄ + R̄) · Q(n) + T · S
= (T · R) · Qn · T · S
(NAND − Darstellung)
Analog lässt sich für Qn+1 eine Schaltfunktion angeben
Qn+1 = (T · S) · Qn · (T · R)
R
T
Q
S
Q
Abbildung 4.5: Schaltung des RS-Flipflops
Entscheidend für die Speichereigenschaft des Elements ist die Rückkopplung innerhalb der Schaltung (siehe Abbildung 4.5). Der konstante Wert Q zirkuliert, solange
T nicht geändert wird. In Abbildung 4.6 sind zwei unterschiedliche Symbole für das
RS-Flipflop dargestellt.
4.4. Schaltwerke und Speicherelemente
R
T
75
S
S
T
RS-FlipFlop
Q
Q
Q
Abbildung 4.6: Schaltsymbole für das RS-Flipflop
Earle Latch
Beim Earle Larch handelt es sich um ein vereinfachtes Speicherelement (siehe Abbildung 4.7). Es speichert den alten Zustand solange T = 0 und übernimmt den neuen
Zustand von der Eingangsleitung D, sobald T = 1. Dabei darf sich D nicht ändern,
während T = 1 ist.
T
D
Earle Latch
Q
Abbildung 4.7: Earle Latch
(
Qn
Q(n+1) =
D
falls T = 0
falls T = 1
Die Schaltfunktion wird durch folgenden Booleschen Ausdruck beschrieben:
Q(n+1) = T̄ · Q(n) + T · D
= T̄ · Q(n) + T · D + D · Q(n)
D · Q(n) ist mathematisch gesehen überflüssig, da er in den beiden anderen Termen
abgedeckt wird. Er wird jedoch für die technische Realisierung — insbesondere im
Hinblick auf den Takt — benötigt (siehe Abbildung 4.8).
76
Kapitel 4. Bausteine und Komponenten von Rechensystemen
D
T
Q
Abbildung 4.8: Schaltung des Earle Latch
Verwendung des Zusatzterms D · Q(n) :
Hierfür sind zwei Gründe zu nennen:
1) Hazards
Eine Realisierung wird nie perfekt dem theoretischen Modell genügen. So können
bei der Taktung Ungenauigkeiten (Laufzeitunterschiede) auftreten (siehe Abbildung 4.9).
T
Zeit
Es kann kurzzeitig T=T=0
sein!
Abbildung 4.9: Hazards
2) Nicht perfekte Taktflanken
Ein weiteres Problem besteht darin, dass die Taktflanken, die beim Wechsel des
Taktes von T = 0 auf T = 1 entstehen, nicht senkrecht sind. Daher ist die Interpretation des Wertes von T ungenau über eine Zeitspanne nicht vernachlässigbarer
Länge (siehe Abbildung 4.10).
4.4. Schaltwerke und Speicherelemente
77
Zeit
T=0
T undef.
T=1
Abbildung 4.10: Taktflanke
Ohne D · Q(n) könnte nach der ersten Taktphase (T = 1) kurzzeitig T = T̄ = 0 gelten
und damit Q(n+1) = T̄ · Q + T · D = 0 unabhängig von D, in der zweiten Taktphase
(T̄ = 1) gilt: Q(n+1) = T̄ · Q ∪ T · D = 0 (unabhängig von D).
78
Kapitel 4. Bausteine und Komponenten von Rechensystemen
KAPITEL 5
Die Arithmetisch-Logische Einheit
In diesem Kapitel werden Rechenwerke für die Addition, Multiplikation und Division besprochen. Dabei werden insbesondere für die Addition verschiedene Methoden vorgestellt.
Zentraler Bestandteil der Arithmetisch-Logischen Einheit (Arithmetic-Logical Unit,
ALU) ist eine schnelle Hardware zur Ausführung der arithmetischen Grundfunktionen
• Addition (Subtraktion)
• Multiplikation
• Division
Interessant sind neben der Ausführungsgeschwindigkeit auch die Kosten dieser Rechenwerke. Beide Kriterien lassen sich durch die Wahl geeigneter Methoden zur
Addition, Multiplikation und Division entscheidend beeinflussen.
Die einfachste Additionsmethode bei Stellenwertcodierung im 2-Komplement ist
aus der Schule bekannt. Man addiert zwei ganzzahlige, n-stellige Summanden komponentenweise und reicht den Übertrag zur nächsten Komponente weiter:
Summand 1:
Summand 2:
Summe:
an−1
bn−1
sn−1
...
...
...
an−2
bn−2
sn−2
a0
b0
s0
Ein Addierwerk, das diese Methode realisiert, ist in Abbildung 5.1 zu sehen.
Beispiel: Addition nach Schulmethode
+
(1)
1
1
0
0
0
1
79
1
0
0
1
1
0
0
1
1
80
Kapitel 5. Die Arithmetisch-Logische Einheit
an-1 bn-1
+
a1 b1
a0 b0
+
+
...
sn=cn-1 sn-1
c1 s1
c0
s0
Abbildung 5.1: Addition nach Schulmethode
5.1 Addition und Subtraktion
Im Folgenden werden zunächst mit dem Halbaddierer (Halfadder, HA) und dem
Volladdierer (Fulladder, FA) zwei Additionskomponenten eingeführt, aus denen
sich viele Rechenwerke zusammensetzen lassen. Einige dieser Rechenwerke werden
dann im Anschluss diskutiert.
5.1.1
Halbaddierer
a
b
HA
c
s
Abbildung 5.2: Symbol für einen Halbaddierer
Der Halbaddierer wird als Schaltkomponente durch das in Abbildung 5.2 dargestellte
Symbol notiert. Er besitzt zwei Eingänge a und b, für welche die Summe s und der
Übertrag c (Carry) berechnet werden soll. Um den Halbaddierer durch eine Schaltung
zu realisieren, sollen zunächst Boolesche Ausdrücke für c und s entwickelt werden.
Deren Funktionstabellen sind gegeben durch:
a
0
0
1
1
b
0
1
0
1
s
0
1
1
0
c
0
0
0
1
5.1. Addition und Subtraktion
81
Hieraus ergeben sich die Minimalpolynome als
c = a·b
s = a·b+a·b ( ≡ a⊕b )
Obwohl es sich um eine Minimalpolynomdarstellung handelt, ist diese Darstellung
nicht kostenminimal:
Laufzeit (Gatterstufen)
Kosten nach Def. aus Kap. 4 (Zahl der Eingänge)
Übertrag c
1
2
Summe s
2
6
Eine bessere Realisierung wird erreicht durch:
s = a · b + a · b ≡ (a + b) · (a + b) ≡ (a + b) · c, da c = a · b
Man beachte, dass es sich nicht um ein Minimalpolynom handelt, weil kein klammerfreier Ausdruck vorliegt.
Laufzeit (Gatterstufen)
Kosten nach Def. aus Kap. 4 (Zahl der Eingänge)
Übertrag c
1
2
Summe s
2
4
Der Halbaddierer lässt sich somit durch die in Abbildung 5.3 dargestellte Schaltung
realisieren.
a
b
c
s
Abbildung 5.3: Schaltung für den Halbaddierer
5.1.2
Volladdierer
Der Volladdierer verfügt über einen weiteren Eingang cin . Dieser ist verwendbar, um
einen Übertrag aus der Summierung der vorhergehenden Komponenten zu verarbeiten. Wie in Abbildung 5.4 gezeigt, kann ein Volladdierer durch zwei Halbaddierer
realisiert werden (Klammerung: (a + b) + cin ).
82
Kapitel 5. Die Arithmetisch-Logische Einheit
a
b
cin
HA1
a b cin
FA
HA2
cout
cout s
s
Abbildung 5.4: Schaltung und Schaltsymbol eines Volladdierers
Die Kosten ergeben sich aus den Kosten der Halbaddierer und des zusätzlichen
OR-Gatters:
KostenFA = 2 · KostenHA + 2 = 14
Die Laufzeit hängt ebenso von der der Halbaddierer ab und beträgt 4 Stufen, wenn
alle Eingänge gleichzeitig anliegen, oder 2 Stufen, wenn cin später eintrifft.
Logik des Volladdierers
Als Boolesche Ausdrücke für den Übertrag und die Summe erhält man:
cout = 1 ⇔ a + b + cin ≥ 2
s = 1 ⇔ a + b + cin = 1 mod 2
also:
cout
= a · b + (a ⊕ b) · cin
= a · b + (a + b) · cin
s = (a ⊕ b) ⊕ cin
= a · b · cin + a · b · cin + a · b · cin + a · b · cin
Die Kosten betragen k(s) = 16, das heißt dieser Ausdruck ist für eine praktische
Realisierung nicht empfehlenswert.
5.1.3
Carry-Ripple-Addierer
Der Carry-Ripple-Addierer ist ein Addierwerk, welches gemäß Abbildung 5.5 aus
n in Serie geschalteten Volladdierern aufgebaut ist. Es handelt sich um einen Paralleladdierer.
5.1. Addition und Subtraktion
83
Addiert wird in der 2-Komplement-Darstellung. Eine Subtraktion kann ebenfalls
durchgeführt werden, indem alle Bits des zweiten Summanden b gekippt und c−1 auf
1 gesetzt werden. Also: a + b setzt c−1 := 0 und a − b setzt c−1 := 1 voraus.
an-1 bn-1
an-2 bn-2
FAn-1
FAn-2
sn-1
a0 b0
...
sn-2
c-1
FA0
s0
Abbildung 5.5: Carry-Ripple-Addierwerk
Logik
Der Boolesche Ausdruck für den Übertrag ci zum Volladdierer FA(i+1) lautet:
ci = ai · bi + (ai ⊕ bi ) · ci−1
= ai · bi + (ai + bi ) · ci−1
Sei zur Abkürzung: ki := ai · bi (Konjunktion) und di := ai + bi (Disjunktion) definiert.
Dann hat der Boolesche Ausdruck die Form:
ci = ki + di · ci−1
Die verwendete Rekursionsformel hat ihren Start mit c−1 und ist eine Funktion der
Form
ci = f (ki , di , ci−1 , . . . , c−1 ) für i = 0, . . . , n − 1.
Laufzeit
Die Rekursionsformel zeigt, dass sich Zwischenergebnisse durch Eintreffen eines
Übertrags von rechts ändern können. Dies führt in der Schaltung zu einer Laufzeiterhöhung. Die maximale Laufzeit beträgt etwa 2 · n Gatterstufen. Dies ist der Fall,
wenn ein Übertrag ganz rechts entsteht und durch alle Stellen propagiert (fortgeleitet)
wird.
Beispiel: Subtraktion mit hoher Laufzeit
84
Kapitel 5. Die Arithmetisch-Logische Einheit
Sei b = (000101011) von a = (100101011) zu subtrahieren. Also ist c−1 = 1, b wird gekippt
und auf a addiert (2-Komplement):
+
(1)
1
1
1
0
1
0
0
1
0
1
0
0
0
1
0
1
0
0
0
1
0
1
0
0
1
0
0
c−1 = 1
Eine Propagationskette ist ein Abschnitt zwischen zwei Stellen, an denen beide
Summanden die gleichen Werte haben. Innerhalb einer solchen Kette wird ein auftretender Übertrag weitergeleitet. Beim Komponentenpaar (0, 0) wird der Übertrag
aufgefangen und beim Paar (1, 1) entsteht sowieso ein Übertrag, d.h. ankommender
ein Übertrag von rechts muss nicht mehr weitergeleitet werden.
Beispiel: Propagationsketten
Die Zahlen (0101101101) und (0110100111) haben folgende Propagationsketten:
0 1 0 1 1 0 1 1 0 1
0 1 1 0 1 0 0 1 1 1
2
4
2
3
3
Die Laufzeit beträgt 4 · 2 + 2, da die maximale Propagationskette die Länge 4 hat. Die
zusätzliche 2 ergibt sich aus der Tatsache, dass der rechte Volladdierer zwei Gatterstufen
mehr braucht.
Falls 0 und 1 gleich häufig und unabhängig voneinander auftreten, gilt: Die Länge
der längsten Propagationskette ist im Mittel log2 (n) und im schlechtesten Fall n lang.
5.1.4
Serieller Addierer
Die serielle Addition entspricht dem handschriftlichen Addieren mit Übertrag. Dieses Addierwerk enthält nur einen Volladdierer, in den die n-stelligen Binärzahlen
komponentenweise geleitet werden. In jedem Takt werden Komponenten ai und bi
addiert, die berechnete Summenkomponente si gespeichert und ein gegebenenfalls
entstehender Übertrag c bei der Addition der Komponenten ai+1 und bi+1 berücksichtigt. Realisiert werden kann ein solches Addierwerk gemäß Abbildung 5.6, also
mit einem Volladdierer, zwei n-stelligen Schieberegistern und einem 1-stelligen Register zur Aufnahme des Übertrags.
an-1 .....a0
bn-1 .....b0
sn-1 .....s0
FA
c
Abbildung 5.6: Serielles Addierwerk
5.1. Addition und Subtraktion
Mikroprogramm
Der Vorgang des seriellen Addierens lässt sich durch ein so genanntes Mikroprogramm beschreiben. Sei hierzu Z eine Zählvariable, welche die Takte zählt. Sie
wird mit n initialisiert. Die Steuervariable V gibt an, ob eine Addition (V = 0) oder
Subtraktion (V = 1) durchgeführt werden soll, wodurch eine Berechnung in der 2Komplement-Arithmetik realisiert wird. Zu beachten ist, dass die in eckigen Klammern stehenden Befehle eines Mikroprogramms parallel ausgeführt werden, also in
einem Takt.
Mikroprogramm: Serielle Addition
0 : [ (an−1 . . . a0 ) := Summand1 ;
(bn−1 . . . b0 ) := Summand2 ;
Z := n; c := V ]
1 : [ bi := bi ⊕V , für i = 0, . . . , n − 1 ]
// falls V =1 wird b komponentenweise gekippt
// => Subtr. im 2-Komplement
2 : [ ai := ai+1 ; bi := bi+1 ( für i = 0, . . . , n − 2)
// => Rechtsshift von a und b
c := cFA (a0 , b0 , c); an−1 := sFA (a0 , b0 , c);
Z := Z -1; bn−1 := 0 ]
3 : if Z > 0 then
goto 2
4 : Stop
In Programmzeile 2 werden (2 · n + 2) Operationen parallel ausgeführt.
Beispiel: Serielle Addition
Seien a = (011) und b = (010) zu addieren:
1.Takt (Z=3)
011
010 c = 0
2.Takt (Z=2)
1 | 01
0 | 01
3.Takt (Z=1)
01 | 0
00 | 0
Ergebnis (Z=0)
101
000
c=0
c=1
c=0
85
86
Kapitel 5. Die Arithmetisch-Logische Einheit
5.1.5
Von-Neumann-Addierer
Bei dem Von-Neumann-Addierwerk handelt es sich um ein einfaches getaktetes
Paralleladdierwerk (siehe Abbildung 5.7). Es ist aus n parallel arbeitenden Halbaddierern aufgebaut. Jedem Halbaddierer sind die Register ai und bi zugeordnet. Das
Register 1 (an−1 . . . a0 ) dient der Speicherung der Zwischensumme. Es enthält auch
die Endsumme. Das Register 2 (bn−1 . . . b0 ) speichert die von den Halbaddierern gebildeten Überträge.
Summen und Überträge der HA werden solange in die Register 1 beziehungsweise
Register 2 zurückgeschrieben, bis Register 2 den Wert Null enthält.
an-1
an-2
HA
HA
bn-1
bn-2
a1
a0
HA
HA
b1
b0
c
...
Abbildung 5.7: Von-Neumann-Addierwerk
Beispiel: Von-Neumann-Addition mit Dezimalzahlen
Sei dieses Verfahren auf zwei Dezimalzahlen angewandt. Sie befinden sich in den zwei
Registern:
a = (98725)
b = (17282)
Es ergeben sich folgende Registerinhalte, wobei die Berechnung einer Stelle mit Übertrag
hervorgehoben ist:
a
b
a
b
a
b
a
b
1
1
0
1
0
9
1
0
1
1
0
1
0
8
7
5
0
5
1
6
0
7
2
9
1
0
0
0
0
2
8
0
0
0
0
0
0
5
2
7
0
7
0
7
0
Seien W(a) und W(b) die Dezimalwerte der Inhalte der Register a und b. Das Verfahren ist korrekt, weil die Invarianzeigenschaft W(a) + W(b) = Summenwert unab-
5.1. Addition und Subtraktion
hängig vom aktuellen Takt gilt. Das Verfahren terminiert, weil pro Takt mindestens
ein Bit des Registers b zu Null wird. Man kann zeigen, dass wenn Nullen und Einsen
in a und b gleichverteilt und unabhängig voneinander sind, das Verfahren im Mittel
nach log2 n Takten stoppt. Es benötigt maximal (n + 1) Takte.
Bei der Subtraktion im 2-Komplement werden alle Bits von b gekippt und im zweiten Takt wird b0 = 1 gesetzt.
Beispiel: Binäre Von-Neumann-Addition
Für a = (11110101)2 = (−11)10 und b = (11100101)2 = (−27)10 ist a − b zu berechnen.
Hierzu wird b zunächst invertiert: b′ = (00011010)2 .
Nach von-Neumann:
Takt 1 11110101
00011010
————
Takt 2 11101111
00100001 c−1 = 1, da Subtraktion im 2-Komplement
————
Takt 3 11001110
01000010
————
Takt 4 10001100
10000100 Gesamtübertrag ignorieren (2-Komplement)
————
Takt 5 00001000
00001000
————
Takt 6 00000000
00010000
————
Takt 7 00010000 Die Summe hat den Wert W(a) = 16.
00000000 Stopp, weil Register 2 den Inhalt (0 . . . 0) hat.
Realisierung und Ablaufsteuerung durch ein Mikroprogramm
Wie für die serielle Addition wird nun für die Von-Neumann-Addition ein Mikroprogramm angegeben. Anschließend wird dieses in einer Diodenmatrix fest verdrahtet. Das Programm addiert (bzw. subtrahiert) binäre Zahlen in der 2-KomplementDarstellung. Um Überläufe zu erkennen, wird das Vorzeichen verdoppelt. Wiederum
werden die in eckigen Klammern stehenden Befehle parallel ausgeführt.
Mikroprogramm: Von-Neumann-Addition
0 : [ A=(an−1 . . . a0 ) := Summand1 ;
B=(bn−1 . . . b0 ) := Summand2 ;
V := 0 , falls Addition ; V := 1 , falls Subtraktion ]
1 : [ bi := bi ⊕ V für i = 0, . . . , n − 1 ]
// falls V =1 wird b komponentenweise gekippt
2 : if B ∪ V 6= 0 then
[ ai := ai ⊕ bi für i = 0, . . . , n − 1;
87
88
Kapitel 5. Die Arithmetisch-Logische Einheit
bi+1 := ai · bi für i = 0, . . . , n − 2;
b0 := V ; V := 0; goto 2 ]
else
[ V := an−1 ⊕ an−2 ; goto 3 ]
3 : if V 6= 0 then
goto 5
4 : Stop ohne Überlaufwarnung
5 : Stop mit Überlaufmeldung
Ablaufsteuerung
Für die Steuerung des Ablaufs eines Programms in hardwarenaher Form sind folgende Schritte umzusetzen:
a) Es muss festgestellt werden, welcher Takt vorliegt.
b) Es muss erkannt werden, welcher Teiltakt vorliegt (und welche Bedingungen aufgrund der Registerzustände gegeben sind).
c) Es ist die Nummer des folgenden Taktes zu berechnen.
d) Die Mikrooperationen (Mikrobefehle) sind auszuführen.
e) Die durch die Mikrooperationen beeinflussten Register sind zu takten.
Folgeadresse
Taktmatrix
Steuermatrix
Adresse
Bedingungen
Befehlsausführung
Decodierung
Eingabe Startadresse
(zu Beginn)
Abbildung 5.8: Ablaufsteuerung
Ablaufsteuerungen werden durch Diodenmatrizen oder PLA’s (Programmable Logic Array) realisiert. Dies sind Felder sich kreuzender Leitungen (siehe Abbildung 5.9).
Die Ausgangsleitungen stehen orthogonal zu den Eingangsleitungen. Eingangswerte
werden mittels spezieller Dioden auf die Ausgangswerte umgesetzt. Der verknüpfende Kreis zwischen Eingangs- und Ausgangsleitungen bildet ein OR, das heißt,
eine auf der Eingangsleitung anliegende Eins wird auf die gesamte Ausgangsleitung
übertragen. Der Strich hingegen hat den Charakter eines logischen AND: Die Ausgangsleitung hat nur dann den Wert Eins, wenn mindestens alle über den Strich an
sie angeschlossenen Eingangsleitungen eine Eins haben.
Diesen Schritten sind in einer fest verdrahteten Realisierung eines Mikroprogramms
folgende Teilmatrizen zugeordnet (siehe Abbildung 5.8):
5.1. Addition und Subtraktion
= Und
89
= Oder
(Keine Diode am Kreuzungspunkt => keine Wirkung)
a
b
c
Eingangsleitungen
d
e
Abbildung 5.9: Dioden
a) Decodiermatrix
b) Bedingungsmatrix
c) Adressmatrix für die Codierung der nächsten Programmadresse
d) Steuermatrix
e) Taktmatrix
Als Beispiel wird nun das Mikroprogramm der Von-Neumann-Addition in eine
Diodenmatrix umgesetzt (siehe Abbildung 5.10). Man trägt Bedingungen im Programm in die Bedingungsmatrix ein und verknüpft sie als Eingänge mit den vertikalen Eingangsleitungen.
Zu den Eingängen zählen auch die Leitungen der Decodiermatrix. Sie liefern die Programmadresse des Mikroprogrammbefehls. Auch sie werden über Und-Dioden mit
den vertikalen Leitungen verknüpft. Die Verknüpfungspunkte entsprechen dabei der
binär codierten Adresse. Zu den Ausgangsleitungen zählen die Taktmatrix, Steuermatrix und die Adressmatrix.
Die Leitungen dieser Matrizen werden über Oder-Dioden mit den vertikalen Eingangsleitungen verknüpft. Die Adressmatrix dient der Bestimmung der folgenden
Programmadresse. In der Steuermatrix werden die Mikrooperationen der Mikroprogrammzeile angestoßen. Die Taktmatrix liefert den Takt für die in den angestoßenen Befehlen verwendeten Register. Die Ausgangsleitungen der letzten drei Matrizen
sind deswegen durch Oder-Dioden mit den vertikalen Leitungen verknüpft, weil nur
eine vertikale Leitung eine Eins zu führen braucht, um einen Mikroprogrammbefehl
zu realisieren.
90
Kapitel 5. Die Arithmetisch-Logische Einheit
Taktmatrix
(Takten der
angesprochenen
Register)
Steuermatrix
(Anstoß zum
Ausführen der
angesprochenen
Mikrooperationen)
TA
TB
TV
Signal “Überlauf”
Signal “kein Überlauf”
V := an-1 Å an-2
V := 0
b0 := V
bi+1 := a i . bi
ai := a i Å bi
B := Summand 2
A := Summand
bi := bi Å V
Adressmatrix
(Berechnung
Folgeadresse)
V=0
Bedingungsmatrix
BÈV=0
Decodiermatrix:
x0
Anfangsbesetzung
(hier nicht gezeigt):
x1
x2 x1 x0 = 000
x2
d.h. Startadresse = 0
0
1 2,then 3,then
4
2,else 3, else
5
Taktnummer (Adresse)
Abbildung 5.10: Diodenmatrix
5.1.6
Erweiterungen des Von-Neumann-Addierers
In diesem Abschnitt wird die Von-Neumann-Addition derart erweitert, dass man
mehrere Summanden addieren kann. Dies wird durch Pipelining oder Parallelität
(Adder-Tree) realisiert. Abbildung 5.11 zeigt eine abkürzende Notation eines VonNeumann-Addierwerks, die im Folgenden verwendet werden soll.
Carry-Save-Addierer
Eine erste Erweiterung besteht darin, im Von-Neumann-Addierer die Halbaddierer
gegen Volladdierer auszutauschen. Aufgrund des somit gewonnenen Eingangs (siehe Kurznotation in Abbildung 5.12, insgesamt hat man nun 3 · n Eingänge und 2 · n
Ausgänge) ist es möglich, nach jedem Takt einen neuen Summanden in das Addier-
5.1. Addition und Subtraktion
91
von-Neumann
Kurznotation
B
...
HA
HA
A
HA-Feld
C
S
Abbildung 5.11: Kurznotation des Von-Neumann-Addierers
werk einzubringen.
neuer Summand
(pro Takt je ein neuer Summand)
FA-Feld
Abbildung 5.12: Carry-Save-Addierer
Das erhaltene Volladdiererfeld wird als Carry-Save-Addierer (CSA) bezeichnet (in
der Kurznotation werden zur Vereinfachung auch Einfachpfeile verwendet). Die Addition von m Zahlen ist nun in m Takten möglich, wenn man diese wie folgt in den
Addierer einbringt:
Takt 1:
Takt 2:
Takt m − 2:
Takt m − 1:
Takt m:
Die ersten drei Summanden werden bearbeitet.
Summanden 1 bis 4 werden bearbeitet.
..
.
Summanden 1 bis m werden bearbeitet.
Auslaufen der Addition nach Von-Neumann-Addition
Abhängig von der Länge der größten Propagationskette,
weiteres Auslaufen der Addition;
bei Wortlänge n im Mittel (log2 n) Takte.
Eine Anwendung besteht in der konventionellen Multiplikation durch eine Folge von
92
Kapitel 5. Die Arithmetisch-Logische Einheit
Additionen (Schulmethode), wie im Abschnitt über die Multiplikation näher noch beschrieben wird. Zur Verdeutlichung dieses Prinzips soll an dieser Stelle die folgende
Skizze genügen:
Produkt
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
Adder-Tree (Wallace Tree)
Um einen Adder-Tree zur parallelen (und somit beschleunigten) Addition aufzubauen, bedarf es der Verwendung mehrerer CSAs, die miteinander verschaltet sind.
Hierzu wird die Taktung aufgetrennt und es werden so viele CSAs hintereinandergeschaltet, wie aufgrund der Summandenzahl erforderlich ist (siehe Abbildung 5.13).
Summand
s1
s2
s3
CSA 1
s4
neuer Summand
CSA 2
CSA
Takt
...
sm
CSA m-2
abschließende
Addition
Abbildung 5.13: Lineare Verschaltung von CSAs
Auf diese Weise hat man bezüglich der Laufzeit keinen Gewinn gemacht. Ordnet man
5.1. Addition und Subtraktion
93
jedoch die CSAs in einem Baum an, so ist es möglich, die Addition in jeder Schicht
des Baums parallel durchzuführen (siehe Abbildung 5.14).
...
...
Adder Tree
Beispiel: m=12
CSA
c s
Abbildung 5.14: Wallace Tree
Die Laufzeit des Adder-Trees für m Summanden ergibt sich aus der Tatsache, dass
im Wesentlichen durch jeden CSA 3 Eingänge auf 2 Ausgänge abgebildet werden,
wobei jedoch die Anzahl der Eingänge nicht immer ein Vielfaches von 3 sein muss.
Sei m die Anzahl aller Eingänge (an den Blättern des Baums oben). Dann beträgt
die Anzahl der Ausgänge nach der i-ten Stufe ungefähr ( 32 )i · m. Für die Laufzeit
ist die Stufenzahl x gesucht, so dass nach der x-ten Stufe zwei Ausgänge vorliegen:
( 23 )x · m = 2.
Man erhält: x · log2 ( 23 ) = log2 ( m2 ) ⇒ x =
5.1.7
log2 ( m2 )
log2 ( 23 )
≈ 1, 72 · log2 m.
Carry-Look-Ahead-Addierer
Die bereits kennen gelernte Carry-Ripple-Addition ist langsam, weil sie n Volladdierer in Serie verwendet. Hierbei entsteht ein Übertragsengpass, weil jeder Volladdierer auf den Übertrag seines rechten Nachbarn warten muss, um sein korrektes
Ergebnis bilden und weiterleiten zu können (siehe Abbildung 5.5).
94
Kapitel 5. Die Arithmetisch-Logische Einheit
Seien di := ai + bi und ki := ai · bi wiederum als Abkürzungen der Disjunktion bzw.
Konjunktion zweier Stellen definiert. Im Abschnitt 5.1.3 wurde bereits eine Rekursionsformel für den Übertrag an der Stelle i hergeleitet:
ci = ai · bi + (ai + bi ) · ci−1 = ki + di · ci−1
Die Rekursionsformel für den Übertrag wird nun aufgelöst, um die Addition durch
direkte Berechnung des Übertrags ci aus den (2 · k + 1) Werten ci−k , a j , b j für j =
(i − k + 1), . . . , i zu beschleunigen:
ci = ki + di · ci−1
= ki + di · (ki−1 + di−1 · ci−2 )
= ki + di · ki−1 + di · di−1 · ci−2
= ...
= ki + di · ki−1 + di · di−1 · ki−2 + di · di−1 · di−2 · ki−3 + . . . + di · . . . · d1 · k0
+di · . . . · d0 · c−1
Für große i ist diese Vorgehensweise zu teuer und unrealisierbar. Daher beschränkt
man sich auf machbare Gruppen und verknüpft diese nach dem Prinzip der CarryRipple-Addition, wie in Abbildung 5.15 anhand eines 12-stelligen Addierwerks für
eine Gruppengröße von 4 gezeigt.
a3 b3
Gruppe 2
c11
Gruppe 1
c7
a0 b0
c-1
Gruppe 0
c3
s3
s2 s1
s0
Abbildung 5.15: Carry-Look-Ahead-Addierer für Gruppengröße 4
Ein Carry-Look-Ahead-Addierer arbeitet im Gegensatz zu einem Carry-RippleAddierer also nicht mit einzelnen Bits, sondern mit ganzen Bitgruppen.
Der Übertrag c7 beispielsweise hat die Form:
c7 = k7 + d7 · k6 + d7 · d6 · k5 + d7 · d6 · d5 · k4 + d7 · d6 · d5 · d4 · c3
Die Laufzeit wird jeweils im Worst-Case von 2 · n bei der Carry-Ripple-Addition
auf 2 · gn bei der Carry-Look-Ahead-Addition verringert, wobei g die Gruppengröße
und gn die Gruppenanzahl ist. n bezeichnet wie oben die Anzahl der Stellen der zu
5.1. Addition und Subtraktion
95
addierenden Zahlen und somit die Anzahl der Eingänge des Addierers. Sie wird um
den Faktor der Gruppengröße verkürzt.
Die erzielte Beschleunigung wird bezahlt durch
• höhere Kosten innerhalb der Gruppen und
• zusätzliche Vorbereitungslaufzeiten, um ki und di bereitzustellen, weil diese sofort benötigt werden. Diese Vorbereitungslaufzeiten wirken sich allerdings erst
dann aus, wenn man das Prinzip auf die 2. Ordnung erweitert, das heißt zur Bildung von Supergruppen übergeht, indem man Carry-Look-Ahead-Addierer
hintereinanderschaltet.
5.1.8
Carry-Skip-Addierer
Die Carry-Skip-Addition ist eine Verbesserung der Addition nach dem Carry-LookAhead-Prinzip. Die aufwändige Schaltlogik der Carry-Look-Ahead-Addition ist
nicht in jeder der ng Gruppen nötig. Man berechnet die Überträge einer Gruppe wie
bei Carry-Ripple in maximal 2 · g Gatterstufen und leitet die Überträge beschleunigt
durch einen einfachen Zusatzschaltkreis über die Gruppen hinweg.
Carry-Skip für eine konstante Gruppengröße g
Sei j ∈ {0, . . . , ng − 1} der Gruppenindex. Ferner seien folgende Abkürzungen eingeführt:
• D j := d( j+1)g−1 · . . . · d jg und
• K j := k( j+1)g−1 + d( j+1)g−1 · k( j+1)g−2 + . . . d( j+1)g−1 · . . . · d jg+1 · k jg
Hierbei sind di und ki wie üblich definiert:
di := ai + bi , ki := ai · bi
Ist K j = 1, so ist in Gruppe j ein Übertrag entstanden. Es gilt für den Gesamtübertag
c j der Gruppe j:
c j = K j + D j · c j−1
Bei Carry-Skip wird ein Übertrag c j einer Gruppe wie folgt berechnet, wobei zwei
Fälle unterschieden werden:
a) D j · c j−1 = 0 und K j = 1 (Übertrag entsteht erst in Gruppe j): Dann ist c j = K j = 1
und wird wie bei Carry-Ripple in maximal 2 · g Gatterstufen berechnet.
96
Kapitel 5. Die Arithmetisch-Logische Einheit
b) D j · c j−1 = 1 (Übertrag wird weitergeleitet): Hier liegt der für die Gesamtlaufzeit
ungünstigste Fall vor. Der Übertrag wird mit D j in zwei zusätzlichen Gatterstufen
weitergeleitet.
Abbildung 5.16 zeigt die Schaltung einer Gruppe des Carry-Skip-Addierers.
ajg bjg
Dj
cj-1
cj
FAg
Kj
...
FAg-1
s(j+1)g-1
s(j+1)g-2
FA1
FA2
sjg+1
sjg
Abbildung 5.16: Gruppe eines Carry-Skip-Addierers
Betrachten wir nun die Laufzeit und Kosten des Addierers. Der Worst-Case der
Laufzeit liegt dann vor, wenn:
a0 = b0 = 1, c−1 = 0 und für alle i = 1, . . . , (n − 2) gilt : ai ⊕ bi = 1.
Das bedeutet, der Übertrag entsteht nur in Gruppe 0, wird nicht sofort weitergeleitet
(da D0 · c−1 = 0) und läuft maximal lange. In diesem Fall ist die Laufzeit:
τ
=
2·g+1
Berechnung
von K0 , c0
+
2 · ( gn − 2)
Übertragsweiterleitung
über ( gn − 2) innere Gruppen
+
2·g
Berechnung von
sn−1
τmin entsteht als Minimum (nach g ableiten, gleich Null setzen,. . .) für:
g = gopt =
r
n
2
Man erhält:
√ √
τmin = 4 · 2 · n − 3
Die Kosten lassen sich direkt aus der Schaltung ablesen (siehe Abbildung 5.16). Zusätzlich zu den im Volladdierer enthaltenen OR-Gattern benötigt man pro Gruppe
ein AND-Gatter mit g Eingängen für D j und zwei Gatter (OR, AND) mit jeweils
zwei Eingängen für die Ermittlung von c j .
Die Kosten kCarry−Skip ergeben sich somit aus den Kosten kCarry−Ripple und den Zusatzkosten der Gatter:
n
4·n
4·n
kCarry−Skip = kCarry−Ripple + · (g + 2 · 2) = 14 · n + n +
= 15 · n +
g
g
g
5.1. Addition und Subtraktion
Carry-Skip mit variabler Gruppengröße
Aus dem letzten Abschnitt wird ersichtlich, dass folgender ungünstiger Fall auftreten
kann: Der Übertrag entsteht in der Gruppe ganz rechts (in Abbildung 5.16), läuft
schnell über die inneren Gruppen und langsam in der letzten Gruppe ganz links.
Eine Idee zur Behebung der Laufzeitunterschiede zwischen den an den Rändern und
in der Mitte liegenden Gruppen besteht nun darin, kleinere Gruppen an den beiden
Rändern und höhere Gruppengrößen zur Mitte hin zu wählen. Dabei ist zu beachten,
dass der Größenunterschied von Gruppe zu Gruppe nicht beliebig sein darf: Falls
die Gruppengröße um mehr als 1 zwischen zwei benachbarten Gruppen differiert,
entsteht ein anders gearteter ungünstigster Fall.
Beispiel: Laufzeiten bei variabler Gruppengröße
Sei i eine Gruppe der Größe i. Unter den Kasten wird die Laufzeit innerhalb der Gruppe
notiert. Die Gesamtlaufzeit wird für den Worst-Case angenommen.
Fall 1: Drei gleich große Gruppen
7
7
7
14
2
15 Gesamtlaufzeit: 31
Fall 2: Drei Gruppen abnehmender Größe
8
7
6
16
2
13 Gesamtlaufzeit: 31
16 15
Gesamtlaufzeit: 31
Fall 3: Abweichung der Gruppengröße um mehr als 1
9
7
5
18
2
11 Gesamtlaufzeit: 31
18 15
Gesamtlaufzeit: 33
Somit liegt hier ein neuer Worst-Case vor, wenn man in der zweiten Gruppe beginnt.
Daher darf nur eine Steigerung der Gruppengröße von beiden Rändern nach innen
pro Gruppe um jeweils den Wert 1 stattfinden. Dies ist aber nicht für alle Längen zu
addierender Zahlen perfekt möglich: Die Summe der Gruppengrößen muss n ergeben, und gleichzeitig muss der Addierer laufzeitoptimal sein. Daher müssen am Rand
gegebenenfalls einzelne Kleingruppen entfernt werden. Einige Beispiele zeigen auch,
dass unter Umständen eine Gruppe aus der Mitte wegzunehmen ist.
Beispiel: Beispiele verschiedener Gruppengrößen
Die Gruppen werden mit ihrer Größe in einem Tupel notiert.
1) Für n = 56 :
Hier liegt einer der wenigen optimalen Fälle vor.
Gruppengrößen: (1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1)
Laufzeit: maximal 29 Gatterstufen.
2) Für n = 50 :
In diesem Fall ist die Aufteilung nicht so günstig möglich. Man kann von der Situation
im ersten Beispiel ausgehend die Gruppen an den Rändern entfernen:
(3, 4, 5, 6, 7, 7, 6, 5, 4, 3)
oder die drei Gruppen ganz links streichen:
(4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1)
oder die rechten drei Gruppen wegnehmen:
97
98
Kapitel 5. Die Arithmetisch-Logische Einheit
(1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4).
In allen drei Fällen hat man die gleiche Laufzeit von 29 Gatterstufen wie bei n = 56.
3) Für n = 44 :
Hier liegt ein Fall vor, bei dem man ausgehend von
(1, 2, 3, 4, 5, 6, 7, 6, 5, 4, 3, 2, 1) zum einen die Gruppen an den Rändern streichen und die
mittlere 7er- gegen eine 6er-Gruppe tauschen sollte:
(2, 3, 4, 5, 6, 6, 6, 5, 4, 3)
oder an einem Rand Gruppen streicht und in der Mitte zwei Gruppen verkleinert:
(3, 4, 5, 6, 6, 5, 5, 4, 3, 2, 1).
Die Laufzeit beträgt 27 Gatterstufen wie für n = 49.
Die Laufzeit τn eines n-Bit-Carry-Skip-Addierers mit variabler Gruppengröße ist
maximal für:
( √
2 · ⌈ 4 · n + 1⌉ − 1 falls m2 < n ≤ m · (m + 1) , m ∈ N
√
τn =
2 · ⌈ 4 · n⌉ − 1
falls (m − 1) · m < n ≤ m2 , m ∈ N
√
Insgesamt gilt also: τn ≈ 4 · n.
Im Vergleich dazu war die minimale Laufzeit bei konstanter Gruppengröße:
√ √
τkonst.
min = 4 · 2 · n − 3.
Gemessen in unserem Kostenmaß aus Kapitel 4 sind die Kosten fast gleich.
Verallgemeinerungen und Kompromisse
Man kann Gruppen von Carry-Skip-Addierern hintereinander schalten und erhält eine so genannte Supergruppe. Aus mehreren solcher Supergruppen lässt sich dann
ein Carry-Skip-Addierer zweiter Ordnung zusammensetzen (siehe Abbildung 5.17).
Abbildung 5.17: Schaltung zum Carry-Skip-Addierer zweiter Ordnung
Eine Ordnungserhöhung lohnt sich aber nur für sehr große Längen der zu addierenden Zahlen. Sonst fällt der Gewinn geringer aus als der Aufwand für die zusätzliche
5.1. Addition und Subtraktion
Logik, die zur Koordination nötig ist.
Ferner lässt sich auch die Technik des Carry-Skip-Addierers mit der eines CarryLook-Ahead-Addierers kombinieren (siehe Abbildung 5.18). Die Anzahl der zusätzlichen Gatter ist hier jedoch größer.
Abbildung 5.18: Kombination von Carry-Skip und Carry-Look-Ahead
5.1.9
Conditional-Sum-Addierer
Wie bei der Carry-Look-Ahead-Addition werden hier ganze Gruppen bearbeitet, allerdings in verschiedenen Gruppengrößen, nämlich zuerst in 1er, dann in 2er, 4er,. . .
Gruppen. Es findet also immer eine Verdopplung der Gruppengröße statt, die durch
die Zusammenfassung zweier benachbarter Gruppen erfolgt, wie in Abbildung 5.19
skizziert. Diese Zusammenfassung kann parallel realisiert werden.
Abbildung 5.19: Gruppen bei der Conditional-Sum-Addition
Die Conditional-Sum-Addition zeichnet sich dadurch aus, dass sie bei der Zusammenfassung zweier Gruppen die Entstehung eines Übertrags explizit berücksichtigt.
Eine Gruppe wird durch 4 Einträge repräsentiert:
99
100
Kapitel 5. Die Arithmetisch-Logische Einheit
c0
c1
|
|
S0
S1
← 0: Kein Carry von rechts
← 1: Carry von rechts
mit c0 , c1 ∈ {0, 1} und S0 , S1 ∈ {0, 1}∗ . Die Länge von S0 und S1 variiert je nach
Gruppengröße.
Bei der Betrachtung einer Gruppe werden zwei Fälle unterschieden:
1. Für den Fall, dass die rechte Nachbargruppe keinen Übertrag liefert, lautet das
Ergebnis der betrachteten Gruppe (c0 , S0 ), wobei c0 den Übertrag und S0 die
Summenbits darstellen.
2. Für den Fall, dass die rechte Nachbargruppe einen Übertrag weitergibt, lautet
das Ergebnis der betrachteten Gruppe (c1 , S1 ).
Zusammenfassung zweier Gruppen
Die Zusammenfassung zweier Gruppen geht sehr systematisch. Die Gruppen A und
B werden zu einer neuen Gruppe AB wie folgt zusammengefasst:
Gruppe A
c0A | SA0
c1A | SA1
c0AB
c1AB
Gruppe B
c0B | SB0
c1B | SB1
Neue Gruppe AB
0
|
SAB
1
|
SAB
← 0: Kein Carry von rechts
← 1: Carry von rechts
← 0: Kein Carry von rechts
← 1: Carry von rechts
∗ ist dabei die Summe der Längen von S∗ und S∗ .
Die Länge von SAB
B
A
Betrachten wir zunächst die obere Zeile der neuen Gruppe, d.h. den Fall, in dem
0 können dann die
rechts kein Übertrag anliegt. Als rechte Hälfte der Summenbits SAB
Summenbits SB0 der Gruppe B übernommen werden. Nun ist zu unterscheiden, ob
Gruppe B einen Übertrag an Gruppe A weiterleiten würde, was durch c0B angezeigt
0 die Bits S0 und als
wird. Ist c0B = 0 werden als linke Hälfte der Summenbits SAB
A
Übertrag c0AB das Bit c0A übernommen. Ist c0B = 1 muss für die Gruppe A ein einge0 wird S1 und als
hender Übertrag berücksichtigt werden, d.h. als linke Hälfte von SAB
A
Übertrag c0AB wird c1A übernommen.
Die untere Zeile der neuen Gruppe ergibt sich analog.
5.1. Addition und Subtraktion
101
Die formalen Regeln für die Zusammenfassung zweier Gruppen lauten somit (hierbei
sei ◦ der Konkatenationsoperator):
 0
 cA , falls c0B = 0
0
cAB =
 1
cA , falls c0B = 1
c1AB =
 0
 cA , falls c1B = 0
0
SAB
=
 0 0
 SA ◦ SB , falls c0B = 0
1
SAB
=
 0 1
 SA ◦ SB , falls c0B = 0
Oder kürzer (für i ∈ {0, 1}):

c1A , falls c1B = 1

SA1 ◦ SB0 , falls c0B = 1

SA1 ◦ SB1 , falls c0B = 1
ci
ciAB = cAB
ci
i
SAB
= SAB ◦ SBi
Die Angabe einer Schaltlogik für diese Zusammenfassung ist relativ einfach. In der
Stufe 0 ist jede Gruppe ein Bitpaar (ai , bi ). Die Gruppengröße ist 1.
Die Logik für die Stufe 0 lautet daher:
c0 = ai · bi
c1 = ai + bi
S0 = S1
S1 = ai ⊕ bi ⊕ 1 = ai · bi + ai · bi = c0 + c1
Die Logik höherer Stufen bedeutet die Umsetzung der Fallunterscheidungen durch
eine Torschaltung:
x :=
wird durch die Schaltung

 α, falls γ = 0

β, falls γ = 1
x := γ · α + γ · β
102
Kapitel 5. Die Arithmetisch-Logische Einheit
realisiert.
Die Kosten dieser Schaltung nach der Definition aus Kapitel 4 betragen 6.
Beispiel: Conditional-Sum-Addition
Die Zahlen a = (1101000110) und b = (0101011001) sind zu addieren (cin = 0) bzw. zu
subtrahieren (cin = 1).
Stufe
1
0
1
1
0
0
1
1
0
0
0
1
0
1
1
0
1
0
0
1
a
b
0
0 1
1 0
1 0
1 1
0 0
0 1
1 0
1 1
0 0
0 1
0 1
1 0
0 1
1 0
0 1
1 0
0 1
1 0
0 1
1 0
cin = 0
cin = 1
1
1
1
00
01
0
0
11
00
cin = 0
cin = 1
2
1
1
00
01
0
0
1111
0000
cin = 0
cin = 1
3
1
1
00
01
0
0
10011111
10100000
cin = 0
cin = 1
4
1
1
0010011111
0010100000
cin = 0
cin = 1
10
11
0
0
01
10
0
1
1001
1010
0
1
11
00
0
1
Laufzeitbetrachtungen
Dieser Additionsalgorithmus ist fast optimal, denn es ist beweisbar, dass (log2 n) eine
untere Schranke für die Laufzeit der Addition zweier n-stelliger Zahlen ist.
• Man benötigt (⌈log2 n⌉ + 2) Stufen für die Addition, wobei die letzte Stufe für
die Auswahl des Endergebnisses nötig ist, das heißt, der Summe oder Differenz
je nach cin .
• Man braucht 2 · (⌈log2 n⌉ + 2) Gatterstufen, denn es sind für jede Stufe je ein
AND- und ein OR-Gatter mit jeweils zwei Eingängen nötig.
Neben der günstigen Laufzeit besteht ein weiterer Vorteil darin, dass gleichartige und
billige Gatter verwendet werden (AND2 , OR2 ). Außerdem ist ein symmetrischer und
synchroner Ablauf möglich.
5.2 Multiplikation
In diesem Abschnitt werden Verfahren zur Multiplikation zweier Binärzahlen diskutiert. Zunächst wird die Multiplikation nach der Schulmethode betrachtet, anschließend werden beschleunigte Methoden vorgestellt.
Die Darstellung der Binärzahlen erfolgt in der Betrag+Vorzeichen-Codierung. Sie
eignet sich gut, weil die Multiplikation auf die Addition zurückgeführt wird. Das Vorzeichenbit der Produktbinärzahl ergibt sich durch Anwendung des XOR-Operators
auf die Vorzeichenbits des Multiplikanden und Multiplikators.
5.2. Multiplikation
103
Folgende Bezeichnungen werden vereinbart:
Multiplikand MD = (MDn−1 . . . MD0 )
Multiplikator MQ = (MQn−1 . . . MQ0 )
Faktor 1:
Faktor 2:
Beide Faktoren müssen vorzeichenlos sein. Um vorzeichenbehaftete Werte zu multiplizieren oder zu dividieren, geht man daher in drei Schritten vor:
1. Abfrage der Vorzeichen und Werte vorzeichenlos machen.
2. Multiplikation (Division) mit den vorzeichenlosen Werten.
3. Aus den bei Schritt 1 ermittelten Vorzeichen das Vorzeichen des Ergebnisses errechnen (XOR).
5.2.1
Serielle Multiplikation
Eine erste Idee besteht darin, die Multiplikation auf eine Folge von Additionen zurückzuführen. Dazu wird die so genannte Multiplikationsmatrix gebildet, deren
Zeilen addiert werden:
MDi ·MQ j
Produkt:
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
i
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
j
Beispiel: Multiplikationsmatrix
Seien MD = 0111 und MQ = 1011.
Für j ∈ {0, . . . , 3} schreibt man in die j-te Zeile der Matrix den um j Bits nach links
verschobenen Wert von MD, falls MQ j = 1 ist. Sonst wird die Zeile mit entsprechend vielen Nullen besetzt. Anschließend werden die Zeilen komponentenweise addiert
(Schulmethode).
0
0
1
0
1
0
0
0
1
0
0
1
0
1
1
1
1
0
1
1
1
1
0
1
Realisierung
Für das doppelt so lange Produkt brauchen wir zwei miteinander verbundene Register der Länge n. Die einzelnen Additionen sind jeweils um ein Bit gegeneinander
verschoben.
Addiert wird:
104
Kapitel 5. Die Arithmetisch-Logische Einheit
• Eine 0, falls das betreffende Multiplikatorbit MQ j 0 ist.
• MD, falls das betreffende Multiplikatorbit 1 ist.
Im Allgemeinen wird also MD · MQi addiert, wobei i die Nummer des aktuellen Multiplikatorbits ist.
Um die oben skizzierte relative Verschiebung zu realisieren, kann man entweder das
Zwischenergebnis festhalten und MD · MQi um ein Bit nach links verschieben, oder
man hält MD · MQi fest und verschiebt das Zwischenergebnis um ein Bit nach rechts.
Wir wählen die zweite Möglichkeit und verwenden das Register MQ als zweite Hälfte des Produktregisters. Dadurch wird der Multiplikator im Verlaufe der n Multiplikationsschritte überschrieben. Ferner steht das aktuelle Multiplikationsbit immer in
MQ0 (siehe Abbildung 5.20).
Zwischenprodukt
(Zu Beginn = 0)
MP
MQ
MQ0
+
MD
Abbildung 5.20: Schema zur seriellen Multiplikation
Das Mikroprogramm für die serielle Multiplikation lautet:
Mikroprogramm: Serielle Multiplikation
0 : [ MD := Multiplikand ; MQ := Multiplikator ;
MP := 0; Z := n ]
1 : [ Z := Z -1;
if MQ0 =1 then
MP := MP + MD ]
2 : [ shr( MP, MQ );
if Z > 0 then
goto 1 ]
3 : Stop
Hierbei bezeichnet MP das Partialprodukt. Die Operation shr(MP, MQ) veranlasst
einen Rechtsshift des gekoppelten Registers (MP, MQ) um 1 Bit, wobei links Nullen aufgefüllt werden (Betrag+Vorzeichen-Darstellung) und wird rechts rausgeschoben. Falls nicht Betrag+Vorzeichen-, sondern 2-Komplement-Darstellung verwendet
wird, dann wird links das Vorzeichen nachgefüllt. Die 1-Komplement-Codierung ist
wegen des End-Around-Carries ungeeignet.
5.2. Multiplikation
105
Beispiel: Serielle Multiplikation
Seien MD = 0111 und MQ = 1011. Am Anfang ist MP = 0000.
Vorbelegung MD :
0111
MP | MQ :
0000 | 1011
Z := 4
1. Durchlauf
MP := MP + MD :
0111 | 1011
Z := 3
shr(MP, MQ) :
0011 | 1101
MP := MP + MD :
1010 | 1101
Z := 2
shr(MP, MQ) :
0101 | 0110
Nur shr(MP, MQ) :
0010 | 1011
Z := 1
MP := MP + MD :
1001 | 1011
Z := 0
2. Durchlauf
3. Durchlauf
4. Durchlauf
0100 | 1101
shr(MP, MQ) :
Ergebnis: 01001101
5.2.2
Multiplikatorcodierung
Die serielle Multiplikation kann dadurch beschleunigt werden, dass die Addition
von Nullzeilen nicht ausgeführt wird (wie im obigen Mikroprogramm bereits realisiert).
Ein erweiterter Ansatz besteht darin, dass ein Shift über Blöcke von Nullen und Einsen des Multiplikators durchgeführt wird. Hat der Multiplikator die Form MQ =
. . . 01k 0 . . . (. . . , 0, k Einsen, 0, . . .), so kann man unter Zuhilfenahme einer aufwändigen Zusatzlogik k Zyklen zusammenfassen.
Beispiel: Zusammenfassung von Zyklen
Sei MQ = . . . 011110 . . ., wobei die rechte Eins die Nummer u ∈ {0, . . . , n − 1} im Bitwort
trägt.
Eine herkömmliche Berechnung hat die Form:
... 0
(
1
|
8
+
1
|
4
+
1
|
2
+
1
|
1
0 ...
)
·2u · MD
Insgesamt wird also 15 · 2u · MD addiert. Dies ist darstellbar als Addition von 16 · 2u · MD
und anschließender Subtraktion von 1 · 2u · MD. Statt der vier Additionen wird man günstigerweise eine Subtraktion (−1) und eine Addition (+16) durchführen.
Angenommen MQ habe die Form MQ = . . . 01k 0 . . . und man betrachtet MQ von
106
Kapitel 5. Die Arithmetisch-Logische Einheit
links nach rechts. Trifft man auf die linke 0, so addiert man 2k · MD auf das Partialprodukt. Die ersten k − 1 Einsen werden anschließend überlaufen. Tritt die Situation
auf, dass man auf einer 1 stehend als nächstes Bit eine 0 erhält, so subtrahiert man
MD vom Partialprodukt. Bei der Realisierung dieses Vorgehens besteht ein Problem
jedoch darin, zu erkennen, wie lang der Einser-Block ist.
Eine einfache Variante der seriellen Multiplikation ist das Verfahren von Booth.
Hierbei handelt es sich um ein serielles Prüfen des Multiplikators, wobei man sich
nicht nur das aktuelle Bit von MQ (MQ0 ) ansieht, sondern zusätzlich das vorherige
Bit, das hier mit MQ−1 bezeichnet werden soll. Die durchzuführenden Aktionen sind
in folgender Tabelle zusammengefasst:
MQ0
0
0
1
1
MQ−1
0
1
0
1
Wirkung
shr (Shift über Nullen)
+1· MD und shr
−1· MD und shr
shr (Shift über Einsen)
Das Verfahren ist nur dann günstig, wenn in MQ längere Blöcke von Nullen oder
Einsen auftreten. Es ist ungünstig, wenn Nullen und Einsen häufig wechseln.
Das Verfahren von Booth bezeichnet man auch als Multiplikatorcodierung der
Gruppengröße 1, da es einen Spezialfall einer allgemeineren Multiplikatorcodierung darstellt. Betrachten wir nun den allgemeinen Fall der Gruppengröße h:
MQh−1 . . . MQ0
Für die Multiplikatorcodierung muss zusätzlich das Korrekturbit MQ−1 betrachtet
werden:
MQh−1 . . . MQ0 | MQ−1
Falls MQ(h−1) = 1, addiert man statt x = 2h−1 · MQh−1 + 2h−2 · MQh−2 + . . . + MQ0
x = 2h − 2h−1 · MQh−1 + 2h−2 · MQh−2 + . . . + MQ0
Dies wird jedoch auf zwei Zyklen verteilt, indem zunächst −2h−1 · MQh−1 + 2h−2 ·
MQh−2 +. . .+MQ0 addiert, anschließend um h Stellen nach rechts geshiftet und dann
1 · MD addiert wird. Die Information, ob eine Korrektur von 1 · MD aus dem vorherigen Zyklus durchgeführt werden muss, kann anhand von MQ0 abgelesen werden. Im
zweiten Zyklus wird 2h also korrigiert durch:
x′ = −2h−1 · MQh−1 + 2h−2 · MQh−2 + . . . + 2 · MQ1 + MQ0 + MQ−1
5.2. Multiplikation
107
Aufgrund des Shifts über die Gruppe wird durch MQ−1 die Korrektur vorgenommen.
Das Verfahren von Booth arbeitet mit einer Gruppengröße von 1. Somit gilt hier
x′ ∈ {−1, 0, 1}.
Als ein weiteres Beispiel soll nun die Multiplikatorcodierung mit Gruppengröße 2
betrachtet werden. Hierbei fasst man zwei Multiplikatorbits (MQ1 , MQ0 ) zusammen.
Dadurch gibt es nur die vier folgenden Möglichkeiten:
(MQ1 , MQ0 )
(0, 0)
(0, 1)
(1, 0)
(1, 1)
Operation
addiere 0 · MD
addiere 1 · MD
addiere 2 · MD
addiere 3 · MD
und schiebe (MP, MQ) anschließend um 2 Bits nach rechts. Die Anzahl der Additionen kann somit halbiert werden. Im Falle, dass 2 · MD addiert werden muss, führt
man einen Linksshift von MD um ein Bit und eine anschließende Addition durch.
Der kritische Fall ist der letzte, wenn (MQ1 , MQ0 ) = (1, 1) ist. Dann muss das Dreifache des Multiplikators addiert werden. Dieses Vielfache benötigt eine eigene Addition (2 + 1) zu seiner Berechnung. Eine effiziente Lösung besteht nun darin, 3 als
4 − 1 = (+1) · 22 + (−1) · 20 zu interpretieren. Die Wertigkeit von 22 ist im nächsten
Zyklus, d.h. nach zweifachem Rechtsshift des Partialprodukts, 20 . Man wird im Fall
(MQ1 , MQ0 ) = (1, 1) im Zyklus i fälschlicherweise (−1) · MD addieren. Dies wird
im Zyklus (i + 1) korrigiert, indem dann 4 · MD zusätzlich zu der dort anliegenden
Addition addiert wird. Aufgrund des Rechtssshifts über die Gruppenlänge (2 Bits) ist
dann aber nur MQ−1 · MD zu addieren (MQ−1 war im Zyklus i MQ1 ; +4 entspricht
im nächsten Zyklus, der eine um den Faktor 22 = 4 höhere Wertigkeit hat, genau dem
Wert +1).
Dieses Verfahren lässt sich auch anwenden, falls (MQ1 , MQ0 ) = (1, 0); hier wird im
Zyklus i (−2) · MD addiert und im Zyklus (i + 1) durch MQ−1 · MD korrigiert:
+2
=
4
Korrektur
−
2
addiere
(−2) · MD
Insgesamt kann man immer dann so vorgehen, wenn MQ1 = 1 und somit im darauf
folgenden Zyklus MQ−1 = 1 ist. Dies hat den Vorteil, dass nur ein Bit zu prüfen ist,
statt wie im Fall (MQ1 , MQ0 ) = (1, 1) beide.
Die folgende Tabelle zeigt die Aktionen, die in Abhängigkeit von (MQ1 , MQ0 , MQ−1 )
zu vollziehen sind.
108
Kapitel 5. Die Arithmetisch-Logische Einheit
MQ1
MQ0
MQ−1
0
0
1
0
1
0
0
0
0
1
1
0
0
0
1
0
1
0
1
1
1
1
1
1
Operation:
Addiere x · MD mit x = . . .
0
1
-2 (statt 2);
spätere Korrektur: 4
-1 (statt 3);
spätere Korrektur: 4
1 = 0 + Korrektur: 1 (4)
2 = 1 + Korrektur: 1 (4)
-1 = -2 (statt 2) + Korrektur: 1 (4)
spätere Korrektur: 4
0
-1 (statt 3) + Korrektur: 1 (4)
spätere Korrektur: 4
Es gilt: x = (−2 · MQ1 + MQ0 + MQ−1 ) · MD mit −2 ≤ x ≤ 2. Somit sind alle x-Werte
durch Inversion und Shift erhältlich.
Beispiel: Multiplikatorcodierung mit Gruppengröße 2
MQ-1
MQ = 0 0 1 0 0 1 1 0 1 1 1 1 0
+1 -2
5.2.3
+2
-1
0
-1 = x
Adder-Tree und Pipelining
Eine weitere Möglichkeit, um eine Beschleunigung der Multiplikation zu erhalten, ist
die Verwendung eines Adder-Trees, mit dem die benötigten Additionsschritte einer
Multiplikationsoperation parallelisiert werden können. Hieru werde je drei Zeilen der
Multiplikationsmatrix in CSAs eines Adder-Trees gegeben (siehe Abbildung 5.21).
Diese Vorgehensweise eignet sich, um mehrere Multiplikationen nacheinander
auszuführen. Ein Beispiel ist die Bildung der Summe ∑ki=1 ai · bi . Die Multiplikationen werden gemäß Abbildung 5.22 stufenweise durch den Adder-Tree geführt
(Pipelining).
Pipeline pro Einzelmultiplikation zusammen mit Multiplikatorcodierung
Um für eine einzelne Multiplikation ähnlich vorgehen zu können, wird der Multiplikator (zum Beispiel 60 Bits lang) in Gruppen zerlegt. Die Gruppen werden
nacheinander in den Adder-Tree gegeben. Dafür eignet sich besonders eine Gruppengröße von 12 Bits. Auf jede Gruppe wird die Multiplikatorcodierung angewendet, wodurch die Zahl der Vielfachen auf die Hälfte verringert wird, im Beispiel auf
5.2. Multiplikation
109
CSA
Sehr schnell!
Aber: Teuer;
pro Multiplikation
ist zu geg. Zeitpunkt
nur eine Stufe des
Adder-Trees aktiv
...
CSA
Adder Tree
Abschließende Addition
z.B. Carry-Look-Ahead
Abbildung 5.21: Multiplikation als Addition im Adder-Tree
Mult. (i+3)
Mult. (i+2)
Mult. (i+1)
Mult. i
Abbildung 5.22: Pipelining durch Adder-Tree
6. Die Gruppen (im Beispiel 5) werden in einen kleinen Adder-Tree (6 Eingänge)
gegeben. Dieser Adder-Tree muss Rückkopplungen aufweisen, die den errechneten
Wert (mit gleichzeitigem Rechtsshift um die Gruppengröße) mit dem nachfolgenden
neuen Wert zusammen verarbeiten (siehe Abbildung 5.23). Von den Rückkopplungen
hängt die Laufzeit ab.
Ist die Rückkopplungsschleife bis oben zu den Blättern des Adder-Trees gelegt, so
ist keine hohe Taktfrequenz möglich. Ein Adder-Tree mit kurzer Rückkopplungsleitung ist dagegen schneller.
110
Kapitel 5. Die Arithmetisch-Logische Einheit
Zeit
Gr 1 Gr 2 Gr 3 Gr 4
Gr 1 Gr 2 Gr 3
zusätzliche CSAs
für Rückkopplungseingänge mit Shift
um 12 Stellen
Gr 1 Gr 2
+ Gr 1
Rückkopplung
Abbildung 5.23: Adder-Tree für Einzelmultiplikation
5.3 Division
Wie bei der Multiplikation wird zunächst mit der seriellen Division ein einfaches
Divisionsverfahren vorgestellt. In einem weiteren Abschnitt wird mit der iterativen
Division eine wesentlich elegantere Methode betrachtet, welche für die iterative Berechnung von Quadratwurzeln modifiziert wird. Es seien folgende Abkürzungen
eingeführt:
DR:
DD:
DE:
5.3.1
Divisor
Dividend
Quotient
Serielle Division
Die serielle Division stellt eine Analogie zur seriellen Multiplikation dar. Sie entsteht durch Umkehrung des entsprechenden Vorgangs bei der Multiplikation (siehe
Abbildung 5.24).
Es besteht folgende Analogie:
Produkt
= Multiplikator
Multiplikant
Dividend
= Quotient
Divisor
Das folgende Mikroprogramm beschreibt die Division nach der Schulmethode für
den binären Fall. Seien (DD, DE) = [DDn−1 , . . . , DD0 , DEn−1 , . . . , DE0 ] das Dividendenregister, (DR) = [DRn−1 , . . . , DR0 ] das Divisorregister und (DE) = [DEn−1 , . . . , DE0 ]
das Quotientenregister. (DD, DE) ist also doppelt so lang wie DR (ggf. auffüllen). Die
Zahlendarstellung erfolgt im 2-Komplement. Ferner wird vereinbart, dass Dividend
und Divisor normiert und positiv sind. Es gilt: 0 ≤ W(DD) < W(DR) < 1.
5.3. Division
111
MP
MQ
MQ0
serielle
Multiplikation
bedingte
Addition
MD
doppelt langer Dividend
DD
bedingte
Subtraktion
DE
Quotientenbit q0
serielle
Division
Divisor DR
Abbildung 5.24: Serielle Multiplikation und Division
Mikroprogramm: Division gemäß Schulmethode
0 : [ (DD,DE ) := Dividend ; DR := Divisor ; Z := n ]
1 : [ Z := Z - 1;
if DD ≥ DR then
q := 1; DD := DD - DR
else
q := 0 ]
2 : [ DE0 := q;
if Z > 0 then
shl ( DD, DE ); goto 1
else
shl ( DE ) ]
3 : Stop
Die wesentliche Fallunterscheidung lautet: Ist DD ≥ DR, so subtrahiere DR von DD
und setze das Quotientenbit q0 gleich 1, ansonsten führe keine Subtraktion durch
und setze q0 auf 0.
Am Ende der Programmausführung steht im Register DD der Partialrest der Division, und DE enthält den Quotienten. Der Divisionsrest ist halb so groß wie der Partialrest, daher wendet man den letzten Shift nur noch auf das Quotientenregister DE
an. Für die Korrektheit des Verfahrens wurde vorausgesetzt, dass 0 ≤ W(DD, DE) <
W(DR) < 1 gilt. Diese Variante wird auch als Non-Performing-Division bezeichnet.
112
Kapitel 5. Die Arithmetisch-Logische Einheit
Eine andere Variante ist die Non-Restoring-Division. Sie unterscheidet sich von obiger Variante dadurch, dass in Zeile 1 immer DR von DD subtrahiert wird und diese
Subtraktion gegebenenfalls wieder rückgängig gemacht wird. Anstelle der Abfrage,
ob DD ≥ DR ist, mit der Konsequenz
• falls ja, Subtraktion und q := 1
• falls nein, nur q := 0
kann man auch wie folgt vorgehen (für W(DR) > 0):
• falls W(DD, DE) ≥ 0, subtrahiere DR, ansonsten addiere DR
• falls das Ergebnis (neuer Wert von (DD, DE)) ≥ 0, q := 1, ansonsten q := 0
• falls am Ende der entstehende Rest negativ ist, korrigiere durch Addition von
DR.
Mikroprogramm: Non-Restoring-Division
0 : [ (DD,DE ) := Dividend ; DR := Divisor ;
Z := n ; DE0 := 1 ]
1 : [ Z := Z - 1;
if DE0 = 1 then
DD := DD - DR
else
DD := DD + DR ]
2 : [ DE0 := DDn−1 ;
if Z > 0 then
shl ( DD, DE ); goto 1
else
shl ( DE ); if DDn−1 = 1 then DD := DD + DR ]
3 : Stop
In Zeile 1 ist DE0 das umgekehrte Vorzeichen des vorherigen Quotientenbits.
Korrektheitsüberlegungen
Geht man davon aus, dass die erstgenannte Methode (Non-Performing) korrekt arbeitet, d.h. Zahlen richtig dividiert, so kann man zur Überprüfung der Korrektheit der
zweiten Methode (Non-Restoring) diese an der ersten messen.
Nach der ersten Methode führt man folgende Operationen aus:
Quotientenbits
0
...
0
↓
↓
Vergleich:
Vergleich:
Keine
Keine
Operation
Operation
Der Partialrest ist stets nicht negativ.
1
↓
Vergleich:
Subtraktion
1
↓
Zuletzt:
Subtraktion
5.3. Division
113
Nach der zweiten Methode geht man wie folgt vor:
Quotientenbits
Partialrest
1
↓
positiv
↓
Subtraktion
...
↓
...
↓
Addition
0
↓
negativ
↓
Subtraktion
0
↓
negativ
↓
Addition
1
↓
positiv
↓
Addition
Bei jedem Quotientenbit 1 sind die Partialreste beider Methoden gleich groß; an den
Stellen, wo die Quotientenbits 0 sind, allerdings nicht:
Position
Quotientenbits
(k − 1)
0
↓
Keine
Operation
...
...
↓
...
1
0
↓
Keine
Operation
Insgesamt ergibt sich: −20 · DR = −DR.
Position
Quotientenbits
(k − 1)
0
↓
Subtraktion
...
...
↓
Addition
...
...
↓
...
0
1
↓
Subtraktion
1
0
↓
Addition
0
1
↓
Addition
Hier erhält man: (−2k−1 + 2k−2 + . . . + 20 ) · DR = −DR.
Beispiel: Non-Restoring-Division
(DD, DE) := (0.10001110010), W(DD, DE) = 569/210 ≈ 0, 55566 . . .,
DR := 0.11110, W(DR) = 30/25 ≈ 0, 9375.
Die Voraussetzung 0 ≤ W(DD, DE) < W(DR) < 1 ist erfüllt.
DD
DE
010001 110011
-DR
110011
100111 10011|0
+DR
000101
001011 0011|01
-DR
101101
011010 011|010
+DR
111000
110000 11|0100
+DR
001110
011101 1|01001
-DR
111111
010010
Shift von DE, da Rest negativ.
+DR
011101 010010
Rest = 29
· 1 , Quotient = 18 · 215 = 0, 5625
25 25
114
Kapitel 5. Die Arithmetisch-Logische Einheit
Beschleunigungsversuche
Die Multiplikatorcodierung ist in vergleichbar einfacher und leistungsfähiger Form
nicht auf die Division übertragbar (niemand hat bisher ein solches Konzept gefunden).
Es besteht jedoch die Möglichkeit, spezielle Divisorvielfache zu verwenden. Die
grundlegende Idee dabei ist, dass die Division schnell ist, wenn der neue Partialrest
möglichst betragsklein ist. Falls sich DD (alter Partialrest) und DR stark unterscheiden, bringt der nächste Zyklus DD − DR oder DD + DR (oder NOOP) noch nicht viel
im Sinne eines kleinen Partialrests. Stellt man den Divisor (DR) dem Dividenden
(DD) in einer Matrix gegenüber, so kann man drei Fälle unterscheiden:
DR
DD
|DD|≪DR:
Bilde DD:=DD-0,5·DR, falls DD ≥ 0
DD+0,5·DR, falls DD < 0
Ist |DD|≈ DR:
Operation wie üblich:
DD := DD-DR, falls DD ≥ 0,
DD := DD+DR, falls DD < 0.
|DD|≫DR:
Bilde DD:=DD-2·DR, falls DD ≥ 0
DD+2·DR, falls DD < 0
Man versucht also, ein geeignetes Vielfaches von DR einzusetzen.
Beispiel: Divisorvielfache
Sei 0 < W(DD) < W(DR). Bilde DD := DD − 0, 5 · DR und berechne zwei Quotientenbits
(00 und 01) je nachdem, ob das Ergebnis negativ oder positiv ist. Hier ist das { 21 , 1, 2}System verwendet worden. Es gibt auch Ansätze, ein { 34 , 1, 23 }- oder ein { 58 , 1, 45 }-System
zu verwenden. Dabei ist der letzte Ansatz besser als der zweite, und dieser ist besser als
das { 21 , 1, 2}-System in folgendem Sinn: Der Betrag des neuen Partialrests ist im Mittel
möglichst klein. Daher ist die Zahl der im Mittel pro Zyklus berechenbaren Quotientenbits
bei dem { 85 , 1, 45 }-System am höchsten.
Ein Kompromiss ist die Table-Look-Up-Methode. Sie arbeitet mit einer Matrix über
Divisor und Dividend. Es wird ein Näherungsquotient aufgrund der ersten Bits von
Dividend und Divisor bestimmt. Dieser Näherungsquotient kann als Startwert in iterativen Verfahren zur Division verwendet werden. Sollen k Bits berücksichtigt werden, müssen in der Tabelle 2k · 2k = 22k Elemente gespeichert werden (siehe Abbildung 5.25).
5.3. Division
115
Divisor
Dividend
0.
0 ...
0 ...
0 ...
0.000
...
0.yyy
...
0.111
0.
x
x
x
0.
... 1
... 1
... 1
2 k Spalten, wenn k
Bits berücksichtigt
Näherungsquotient
Abbildung 5.25: Table-Look-Up-Methode
5.3.2
Iterative Division
In diesem Abschnitt wird ein iteratives Verfahren zur Division vorgestellt. Man geht
dabei von der Rückführung der Division auf eine Folge von Multiplikationen und
Additionen aus. Da die Division im Allgemeinen seltener benötigt wird als die Multiplikation, ist diese Rückführung der Konstruktion einer eigenen Divisionshardware
vorzuziehen und rechtfertigt ein schnelles, aber teures Multiplizierwerk.
Man geht von einem Startwert x0 aus und wendet auf jeden Wert xi eine rekursive
Iterationsvorschrift ϕ an, welche den Wert xi+1 liefert:
x0 → x1 := ϕ(x0 ) → x2 := ϕ(x1 ) → . . . → xi+1 := ϕ(xi ) → . . .
Unter geeigneter Wahl des Startwertes konvergiert ϕ gegen einen Grenzwert. Gilt
x̄ = ϕ(x̄), so heißt x̄ Fixpunkt von ϕ.
Definition: Konvergenz mit Ordnung m
Sei x0 ein geeignet gewählter Startwert und m ∈ N0 .
ϕ konvergiert mit Ordnung m gegen einen Grenzwert x, wenn für den Iterationsfehler
εi := xi − x gilt: εi+1 = O(εm
i ).
Ist m = 1, so konvergiert ϕ mit linearer Geschwindigkeit gegen den Grenzwert; ist
m = 3, so konvergiert ϕ mit kubischer Geschwindigkeit gegen x̄.
Beispiel: Regula Falsi
Sei f eine Funktion, die eine Nullstelle besitzt. Man geht von zwei Stellen x0 und x1 aus,
für die gilt: f (x0 ) < 0 und f (x1 ) > 0 oder umgekehrt. In jedem Schritt legt man eine Gerade
durch die Punkte, welche durch die zwei Stellen und ihre Funktionswerte gebildet werden.
Dann betrachtet man den Schnittpunkt der Geraden mit der x-Achse.
Seien xi und xi+1 die betrachteten Stellen mit xi < xi+1 . Man wendet folgende Iterationsvorschrift an:
if f (Schnittstelle) = 0 then Nullstelle := Schnittstelle;
if f (Schnittstelle) < 0 then xi := Schnittstelle;
116
Kapitel 5. Die Arithmetisch-Logische Einheit
if f (Schnittstelle) > 0 then xi+1 := Schnittstelle;
Das Verfahren konvergiert mit linearer Geschwindigkeit, ist also von der Ordnung m = 1.
Beispiel: Newton-Verfahren
Dieses Verfahren dient ebenfalls der iterativen Ermittlung einer Nullstelle einer Funktion f .
Man geht von einer Startstelle x0 aus und erhält xi+1 durch Anwendung der Iterationsvorschrift ϕ(x) = x − ff′(x)
(x) auf xi (siehe Abbildung 5.26).
f
x x2 x1
x0
Abbildung 5.26: Newton-Verfahren
Das Newtonverfahren konvergiert quadratisch, also mit Ordnung m = 2 gegen eine
Nullstelle x̄ von f (x), sofern x0 geeignet gewählt wird und f ′ (x̄) 6= 0 ist.
Das Newton-Verfahren wird nun verwendet, um ein elegantes Verfahren zur Division
zu konstruieren. Dabei wird 1b aus b wie folgt errechnet:
• Suche eine Funktion f (x), die
• Berechne ϕ(x) = x −
f (x)
f ′ (x)
1
b
als Nullstelle besitzt.
auf xi , wobei ϕ(x) keine Division enthalten soll.
• Führe die Iteration xi+1 = ϕ(xi ) so oft wie nötig durch, bis Konvergenz im
Rahmen der erzielbaren Genauigkeit eintritt.
Versuch 1:
Geht man von der Funktion f (x) = x − 1b mit Nullstelle
brauchbare Iterationsvorschrift:
1
b
x − b1
f (x)
1
ϕ(x) = x − ′
= x−
=
f (x)
1
b
Der Fixpunkt
1
b
muss vorher bekannt sein.
aus, so erhält man keine
5.3. Division
117
Versuch 2:
Sei f (x) = − 1x + b. Diese Funktion hat auch die Nullstelle 1b . Die Iterationsvorschrift
ϕ lautet:
ϕ(x) = x −
f (x)
f ′ (x)
= x−
− 1x + b
1
x2
= x − (−x + b · x2 )
= 2 · x − b · x2
= (2 − b · x) · x
Mit dieser Iterationsvorschrift hat man eine divisionsfreie Formel erhalten. Die Division ist hiermit auf zwei Multiplikationen und eine Subtraktion zurückgeführt worden, die zum Beispiel im 2-Komplement leicht zu handhaben ist. Für b ∈ [ 12 : 1] liegt
beispielsweise die Mantisse einer normalisierten Gleitkommazahl vor.
Die Divisionsvorschrift ist also:
Startwert:
x0 := 1 oder
x0 := Wert nach Table-Look-Up (Näherungswert für 1b )
Iterationsvorschrift:
ϕDiv (x) = (2 − b · x) · x
Beispiel: Iterative Division
Seien b = 0, 85; x0 = 1.
Dann ergeben sich folgende Näherungswerte, wobei an diesen das quadratische Verhalten
des Newton-Verfahrens zu erkennen ist:
x1
= (2 − 0, 85 · 1) · 1 = 1, 15
x2
x3
= 1, 175875
= 1, 1764703
x4
= 1, 1764706. . . .
1
x4 stellt einen relativ genauen Wert von 0,85
dar. Ein besserer Startwert ist 0, 8, denn hier
erhält man obige Näherungswerte schon einen Schritt früher:
x1∗
= 1, 171875
x2∗
x3∗
= 1, 1764526
= 1, 1764705. . . .
ϕDiv konvergiert quadratisch gegen 1b . Der Iterationsfehler des (i + 1)-ten Schrittes ist
kleiner oder gleich Null (es liegt also quadratische Konvergenz von unten vor):
1
1 2
εi+1 = xi+1 − x̄ = (2 − b · xi ) · xi − = −b · xi −
= −b · ε2i ≤ 0, falls 0 < b < 1.
b
b
118
Kapitel 5. Die Arithmetisch-Logische Einheit
Anschaulich bedeutet dies eine Verdopplung der Zahl korrekter Bits (Stellen, Ziffern) bei jedem Übergang von xi zu xi+1 . Der (i + 1)-te Schritt bringt also soviel
wie die ersten i Schritte zusammen. Da das Verfahren nur bei hinreichend genauem
Ausgangswert konvergiert (dann allerdings schnell!), ist der Start mit einem guten
Näherungswert aus der Table-Look-Up-Tabelle sehr zweckmäßig.
Bei verkürzter ungenauer Berechnung der Multiplikationen xi+1 = (2 − b · xi ) · xi ist
die Zeit pro Iterationsschritt kürzer. Die Konvergenzgeschwindigkeit ist dafür aber
etwas schlechter als quadratisch. Für eine kürzere Multiplikation verwendet man die
Schreibweise (2 − b · xi )Tr (Truncated). (2 − b · xi )Tr enthält nur die relevantesten Bits
von (2 − b · xi ).
Ein Vorteil besteht darin, dass (2 − b · xi )Tr mit Multiplikatorcodierung auf wenige,
z.B. 6, Vielfache codiert und in einem kleinen Adder-Tree verarbeitet werden kann.
Ferner wird die Bildung von (2 − b · xi ) vereinfacht.
AEGP (Anderson-Earle-Goldschmidt-Power)
Ein Nachteil der bisherigen Iterationsvorschrift ϕDiv (x) = (2 − b · x) · x besteht darin,
dass die zwei aufeinanderfolgenden Multiplikationen pro Iterationsschritt eine Parallelisierung verhindern.
Ziel ist es, eine gleichschnelle Konvergenz durch zwei parallele Multiplikationen zu
erzielen. Eine Idee besteht darin, dass die erste Multiplikation entfällt, wenn b = 1
ist. Das Verfahren konvergiert dann für jeden sinnvollen Startwert zum Grenzwert 1.
Das Verfahren lautet:
d0
di+1
=
=
Startwert
(2 − di ) · di
Beispiel: Konvergenz von di+1 = (2 − di )di
d0
d1
= 1, 5
= 0, 5 · 1, 5 = 0, 75
d2
= 1, 25 · 0, 75 = 1 − (0, 25)2 = 1 −
1
16
Ein unbrauchbarer Startwert wäre d0 = 5.
Für die Berechnung eines Quotienten
a
b
betrachtet man zwei parallele Folgen:
• Folge 1 mit Startwert b und
• Folge 2 mit Startwert a.
Prinzipiell führt man solange eine Multiplikation der aktuellen Werte von Folge 1
und 2 mit dem gleichen Faktor durch, bis Folge 1 den Grenzwert Eins erreicht hat
5.3. Division
119
(im Rahmen der Genauigkeit). Wenn dies der Fall ist, dann wurde durch Folge 2 der
Wert des Quotienten ab approximiert:
a · r0 · r1 · . . . ri
a a · r0 a · r0 · r1
=
=
= ... =
b b · r0 b · r0 · r1
b · r0 · r1 · . . . ri
a · r0 · . . . ri konvergiert also gegen ba , wenn b · r0 · . . . ri gegen 1 konvergiert.
Es gilt insgesamt:
Startwert
Iterationsvorschrift
Konvergenz
Folge 1
Folge 2
d0 := b
x0 := a
di+1 := di · (2 − di ) xi+1 := xi · (2 − di )
quadratisch gegen
dE = 1
xE = ba
In einer Realisierung sind nun zwei Multiplikationen (di · (2 − di ) und xi · (2 − di ))
pro Iterationsschritt umzusetzen. Sind zwei Multiplizierwerke vorhanden, so kann
man die Multiplikationen parallel ausführen. Stattdessen könnte man auch das Pipelineprinzip verwenden:
Pipeline A:
Pipeline B:
di
xi−1
xi
di
di+1
xi
xi+1
di+1
di+2
xi+1
Zeit→
Ferner kann man die verkürzten Formen (di · (2 − di ))Tr und (xi · (2 − di ))Tr in einen
Adder-Tree geben, wobei man dann zunächst ungenau aber schnell rechnet und im
letzten Schritt die Folge 2 genau berechnet.
5.3.3
Iterative Berechnung von Quadratwurzeln
Um die Quadratwurzel einer Zahl N zu berechnen, kann man ähnlich vorgehen wie
bei der iterativen Division. Man√verwendet wieder das Newton-Verfahren mit einer
geeigneten Funktion f , welche N als Nullstelle besitzt.
Wählt man f (x) = x2 − N, so ergibt sich folgende Iterationsvorschrift für das iterative Wurzelziehen:
f (xi )
xi2 − N
1
N
xi+1 = ϕ(xi ) = xi − ′
= xi −
= · xi +
f (xi )
2 · xi
2
xi
√
Das Verfahren konvergiert quadratisch gegen N.
Beispiel: Iterative Berechnung der Quadratwurzel aus 2
Sei N = 2 und x0 = 100 (ziemlich schlechter Startwert).
Es ergibt sich folgende Näherungsfolge:
120
Kapitel 5. Die Arithmetisch-Logische Einheit
x0
x1
x2
x3
x4
x5
x6
x7
x8
= 100
1
2
=
· (100 +
) ≈ 50 (ungenau)
2
100
≈ 25
≈ 12
≈ 6
≈ 3
1
2
≈
· (3 + ) ≈ 1, 83 (ungenau gerechnet ergäbe sich: 1, 5)
2
3
≈ 1, 46
≈ 1, 4149 . . . (schon recht genau)
Ein großer Nachteil des Verfahrens besteht darin, dass es nicht divisionsfrei ist, da Nxi
in jedem Schritt berechnet wird. Daher kommt man wieder auf eine AEGP-verwandte
Methode zurück.
Man verwendet hier die Folgen (di ) und (xi ) mit:
d0 := N,
x0 := N,
di+1 := di · ri2
xi+1 := xi · ri
wobei ri = 1 + 12 · (1 − di ) ist. Die hier vorliegende Division durch 2 kann durch einen
2
Rechtsshift realisiert werden. Es gilt, dass dn = d0 · r02 · r12 · . . . rn−1
quadratisch gegen
1 konvergiert, wobei auch hier wieder ein geeigneter Startwert vorausgesetzt sei.
Satz:
Die Folge (xi ) konvergiert quadratisch gegen
√
N:
√
N
1
xn = x0 · r0 · r1 · . . . rn−1 → x0 · √ = √ = N
d0
N
Beispiel: Berechnung der Quadratwurzel aus 2
Sei N = 2 und somit d0 = x0 = 2. Man erhält die Folgen (di ), (xi ) und (ri ):
d0 = 2
x0 = 2
r0 = 1 + 21 · (1 − 2) = 12
1
1
1
x1 = 2 · 2 = 1
r1 = 1 + 21 · (1 − 21 ) = 54
d1 = 2 · 4 = 2
25
5
7
d2 = 32
x2 = 4
r2 = 1 + 64
d3 = 0, 9614943 x3 = 1, 3867187 r3 = 1, 0192528
d4 = 0, 998872
x4 = 1, 4134169 r4 = 1, 0005635
d5 = 0, 999989
x5 = 1, 4142133 r5 = 1, 0000005
5.3. Division
121
Beweis:
Es gilt:
√
xn = x0 · r0 r1 · . . . · rn−1 = N · r0 r1 · . . . · rn−1 → N
1
⇔ r0 r1 · . . . · rn−1 → √
N
1
⇔ (r0 r1 · . . . · rn−1 )2 →
N
⇔ N · (r0 r1 · . . . · rn−1 )2 = d0 · (r0 r1 · . . . · rn−1 )2 = dn → 1
Es ist also zu zeigen, dass (di+1 ) gegen 1 konvergiert.
Zunächst ist: di+1 = di · (1 + 21 · (1 − di ))2 = di · (2 − di + 41 · (1 − di )2 ).
Hilfssatz:
Eine Iterationsvorschrift xi+1 := ϕ(xi ) konvergiert genau dann mit Ordnung m
′
gegen x, d.h. für εi = xi − x gilt εi+1 = O(εm
i ), wenn ϕ(x) = x und ϕ (x) = . . . =
ϕ(m−1) (x) = 0 und ϕ(m) (x) 6= 0.
Taylorentwicklung des Fehlers:
εi+1 = xi+1 − x̄ = ϕ(xi ) − x̄ = ϕ(x̄ + εi ) − x̄
∞
∞
ϕk (x) k
ϕk (x) k
· εi − x̄ = ∑
εi + ϕ(x̄) − x̄
= ∑
k=1 k!
k=0 k!
′
m−1 (x̄) = 0 und ϕ(m) (x̄) 6= 0. Daher: εi+1 = O(εm
i ) ⇔ ϕ(x̄) = x̄ und ϕ (x̄) = . . . = ϕ
Es bleibt noch zu zeigen, dass di+1 = di · (2 − di + 14 · (1 − di )2 ) quadratisch gegen
x̄ = 1 konvergiert.
Die Iterationsvorschrift lautet hier:
Ableitungen:
1
2
di+1 = ϕ(di ) mit ϕ(x) = x · 2 − x + · (1 − x) ,
4
1
1
2
ϕ (x) = 1 · 2 − x + · (1 − x) + x · −1 + · 2 · (1 − x) · (−1)
4
4
′
6·x
4
′
(di ) konvergiert gegen 1, weil ϕ(1) = 1, ϕ (1) = 0 und ϕ′′ (1) 6= 0 ist:
ϕ′′ (x) = −2 +
ϕ(1) = 1 · (2 − 1 + 0) = 1 = x̄,
ϕ (1) = 1 · (2 − 1 + 0) + 1 · (−1 + 0) = 0,
1
ϕ′′ (1) = − .
2
′
122
Kapitel 5. Die Arithmetisch-Logische Einheit
5.4 Arithmetik bei redundanter Zahlendarstellung
Die letzten Abschnitte haben gezeigt, dass ein Übertrag in ungünstigen Fällen eine
lange Laufzeit der Rechenoperation bewirkt. Der Übertrag kann sich zum Beispiel
auf die gesamte Addition auswirken. In diesem Abschnitt werden Zahlendarstellungen für die Addition und für die Division besprochen, die auf Kosten einer erhöhten
Redundanz eine beschleunigte Durchführung der Operationen ermöglichen.
5.4.1
SDNR-Darstellung für die Addition
Die grundlegende Idee besteht darin, eine oder mehrere zusätzliche Redundanzziffern einzuführen, in denen sich der Übertrag fängt, falls er überhaupt entsteht. Man
führt zum Beispiel eine zusätzliche 2 zu den binären Ziffern 0 und 1 ein. Die Ausgangszahlen könnte man binär darstellen und das Ergebnis ternär interpretieren. Dies
wird im folgenden Abschnitt präzisiert.
Die Zahlendarstellung ist in Stellenwertform zu einer Basis d. Dabei sind im codierenden Bitwort nun nicht mehr nur die Ziffern 0, . . . , d − 1 zulässig, sondern positive
und negative Ziffern αi ∈ [−r1 : +r2 ], r1 , r2 > 0:
WSDNR (αn−1 , αn−2 , . . . , α0 ) =
n−1
∑ αi · d i
i=0
Um die Notation im Folgenden übersichtlicher zu gestalten, wird −x als x notiert.
Beispiel: Wert einer SDNR-Zahl zur Basis d = 10
WSDNR (23̄14̄) = 2000 − 300 + 10 − 4 = 1706.
Definition: SDNR (Signed Digit Number Representation)
Eine Zahlendarstellung zu einer Basis d, die folgende Eigenschaften hat, heißt SDNR:
1. Symmetrie: r1 = r2 = r
2. Für αi sollen mindestens d verschiedene Werte möglich sein. Der Übertrag (+1 oder
−1) aus der Stelle (i − 1) soll sich in der Stelle i fangen.
Dies ist erfüllt, wenn 2 · r + 1 ≥ d + 2 gilt, also ⌊ d2 ⌋ + 1 ≤ r;
2 · r + 1 ist die Anzahl möglicher Ziffern.
3. Für αi sollen höchstens d nicht-negative Werte zulässig sein, also r ≤ d − 1.
Das Vorzeichen des Wertes einer SDNR-Zahl ist gleich dem Vorzeichen der von links
gesehen ersten Ziffer der Zahl, die nicht 0 ist.
Aus der obigen Definition die (Nicht-)Existenz von SDNR-Darstellungen zu bestimmten Basen abgeleitet werden:
a) Für die Basis d = 2 gibt es keine SDNR-Darstellung:
⌊ d2 ⌋ + 1 ≤ r ≤ d − 1 (Bedingung 2 und 3) liefert für d = 2 :
5.4. Arithmetik bei redundanter Zahlendarstellung
123
1 + 1 ≤ r ≤ 2 − 1, also 2 ≤ 1, was zu einem Widerspruch führt.
b) Für die Basis d = 3 ist eine SDNR-Darstellung möglich:
⌊ 32 ⌋ + 1 ≤ r ≤ 3 − 1, folglich: r = 2 ist hier eindeutig bestimmt.
Somit ist die Codierung festgelegt:
WSDNR (αn−1 , αn−2 , . . . , α0 ) =
n−1
∑ αi · 3i mit
i=0
αi ∈ [−2 : +2].
Beispiel: SDNR-Addition
Es werden die Zahlen (21̄2̄2̄012) und (1̄2̄2̄1222) addiert. Dabei wird das jeweilige Summenbit in der oberen und das Übertragsbit in der unteren Zeile notiert, wobei das Übertragsbit einer Stelle eine Stelle weiter links geschrieben wird. Diese Notation wurde schon
bei der Von-Neumann-Addition verwendet. Im ersten Schritt der Addition wird darauf
geachtet, dass die Summenbits si ∈ [−1 : +1] sind.
0
2
1
1
1
0
1
2
0
1
1
2
2
1
0
1
2
1
1
1
0
0
2
1
1
0
1
2
0
1
1
2
2
1
0
1
Die fettgedruckten Ziffern zeigen, wie man s2 = 2 vermeiden kann: 2 = 3 · 1 − 1. Auf diese
Weise kann im zweiten Schritt der Addition kein Übertrag mehr entstehen.
Im allgemeinen Fall bildet man die Summenbits si im ersten Schritt so, dass sie den
Ziffernbereich nicht bis oben beziehungsweise unten ausfüllen: si ∈ [−(r − 1) : +(r −
1)]. Der Übertrag +1 oder −1 fängt sich dann im zweiten Schritt. Die Addition für
die Basis d und ⌊ d2 ⌋ + 1 ≤ r ≤ d − 1 geschieht wie folgt:
+
+
cn−1
sn
αn−1
βn−1
σn−1
cn−2
sn−1
···
···
···
···
···
c0
α0
β0
σ0
0
s0
Zwischensumme
Vorläufiger Übertrag
Summe
Dabei sind: αi , βi , si ∈ [−r : +r], σi ∈ [−(r − 1) : +(r − 1)] und ci ∈ [−1 : +1].
Für Schritt 1 sind folgende Formeln denkbar:
Sei wmax ∈ [(d − r) : (r − 1)], zum Beispiel also wmax = r − 1.


+1 falls αi + βi > wmax
Setze ci = 0
sonst


−1 falls αi + β1 < −wmax
und setze σi = αi + βi − ci · d, wegen der Invarianzeigenschaft: αi + βi = ci · d + σi .
Dann ist | σi |< r für i = 0, . . . , (n − 1) erfüllt und somit ist Schritt 2 ohne Überträge
möglich.
124
Kapitel 5. Die Arithmetisch-Logische Einheit
5.4.2
Gemischtes SDNR-Verfahren
Die Addition von Zahlen in der SDNR-Darstellung geht sehr schnell. Zu beachten
ist allerdings, dass die Zahlen zunächst in dieser Form codiert sein müssen. Der Aufwand für diese Codierung muss daher berücksichtigt werden. Günstig ist es, das Verfahren zu verallgemeinern, so dass eine Addition von Zahlen durchgeführt werden
kann, wobei eine Zahl in SDNR-Darstellung zur Basis d und die andere in normaler
Stellenwertcodierung zur Basis d vorliegt:
+
+
cn−1
Sn
An−1
bn−1
Tn−1
cn−2
Sn−1
···
···
···
···
···
c0
A0
b0
T0
0
S0
SDNR-Zahl
d-näre Zahl
Zwischensumme
Vorläufiger Übertrag
Summe
Die großen Buchstaben kennzeichnen Ziffern einer SDNR-Zahl, d.h. Ai ∈ [−(d −
1) : +(d − 1)]; die kleinen Buchstaben bezeichnen Ziffern einer d-nären Zahl, also
bi ∈ [0 : (d − 1)].
Die Formeln für Schritt 1 und Schritt 2 der Addition lauten:
Schritt 1:
Setze
ci
(
1 wenn Ai + bi ≥ d − 1
=
0 sonst,
Ti = Ai + bi − ci · d ∈ [−(d − 1) : +(d − 2)]
Schritt 2:
Setze Si = Ti + ci−1 ∈ [−(d − 1) : +(d − 1)], ohne weiteren Übertrag.
Dieses gemischte Verfahren funktioniert auch bei Codierung zur Basis d = 2. Hier
liegt obiges Schema mit entsprechender Wahl der Ziffernbereiche zugrunde:
Ai ∈ {−1, 0, +1}, bi ∈ {0, 1}, Ti ∈ {−1, 0}, ci ∈ {0, 1} für i = 0, . . . , (n − 1) und Si ∈
{−1, 0, 1} für i = 0, . . . , n.
Ai , Ti und ci werden binär codiert (bi liegt binär vor und Si wird umgewandelt):
• Ai auf zwei Binärstellen, wobei sich als Darstellungsform Betrag+Vorzeichen
eignet:
ai,1
0
0
1
1
ai,2
0
1
0
1
Ai
+0
+1
-0
-1
5.4. Arithmetik bei redundanter Zahlendarstellung
• ci und Ti können auf einer Binärstelle codiert werden.
Für die Realisierung der Berechnung eignen sich folgende Formeln:
a) Ai = ai,2 · (1 − 2 · ai,1 ), also ai,2 = Ai mod 2
b) ci = 1 ⇔ Ai + bi ≥ 1 ⇔ Ai = 1 ∨ Ai = 0 ∧ bi = 1
Formel: ci = ai,1 · ai,2 + ai,2 · bi
c) Ti = −1 ⇔ Ai + bi = 1 mod 2 ⇔ ai,2 + bi = 1 mod 2
Formel: Ti = −(ai,2 ⊕ bi ); | Ti |= ai,2 ⊕ bi
d) Formeln für Si = (si,1 ; si,2 ) :
si,2 = 1 ⇔ Si 6= 0 ⇔ Ti + ci−1 = 1 mod 2 ⇔ | Ti | ⊕ci−1 = 1,
also: si,2 =| Ti | ⊕ci−1 = ai,2 ⊕ bi ⊕ ci−1
si,1 =| Ti | oder auch si,1 = ci−1
Die zwei unterschiedlichen Möglichkeiten beruhen auf der Redundanz der Zahlendarstellung.
5.4.3
SRT-Verfahren zur seriellen Division
Dieses Verfahren ist benannt nach Sweeney, Robertson und Tocher und es verbessert
das Prinzip der seriellen Division in der Form, dass der neue Partialrest möglichst
betragsklein gewählt wird. Das Prinzip der seriellen Division besteht aus folgenden
Schritten:
• Subtrahiere vom Dividenden ein geeignetes Vielfaches des Divisors.
• Bestimme Quotientenbit(s) in Abhängigkeit von dieser Subtraktion.
• Wiederhole diesen Vorgang so lange mit jeweils neuem kleineren Partialrest,
bis der Partialrest näherungsweise Null ist (bis also der Quotient vollständig
berechnet ist).
Die Folge der Partialreste X im Verlaufe einer Divisionsoperation zur Basis d ist
gegeben durch:
X n := W(DD, DE) Wert von Register (DD, DE)
X j := d · (X j+1 − q j · W(DR)) für alle j = (n − 1), . . . , 0
Dabei ist q j ∈ {−(d −1), . . . , 0, . . . , (d −1)} ein Quotientenbit. Dieses Quotientenbit
ist nun so zu wählen, dass X j möglichst betragsklein wird, das heißt, für alle q′j gilt:
| X j (q j ) |≤| X j (q′j ) |.
125
126
Kapitel 5. Die Arithmetisch-Logische Einheit
SRT-Division im binären Fall
Man kann folgende zwei Varianten unterscheiden: Das SRT 1-Verfahren ist ziemlich
genau, aber aufwändiger als das SRT 2-Verfahren, welches dafür ungenauer arbeitet.
SRT1:
Es sei vorausgesetzt, dass
1
2
≤ W(DR) < 1 ist. Dann ist SRT 1 definiert durch:
X n := W(DD, DE)
X j := 2 · (X j+1 − q j · W(DR)), für j = (n − 1), . . . , 0, mit:

j+1 > 1 · W(DR)

+1, falls X
2
q j :=
0,
sonst


−1, falls X j+1 < − 21 · W(DR)
SRT2:
Es ist wieder vorausgesetzt, dass
1
2
≤ W(DR) < 1 ist. Dann ist SRT 2 definiert durch:
X n := W(DD, DE)
X j := 2 · (X j+1 − q j · W(DR)), für j = (n − 1), . . . , 0, mit:

j+1 ≥ 1

+1, falls X
2
q j :=
0,
sonst


−1, falls X j+1 < − 21
Hier ist also die Bestimmung von q j einfacher, denn es muss kein expliziter Vergleich
durchgeführt werden, sondern es reicht, die ersten beiden Bits zu prüfen:
j+1
j+1
Seien xn−1 und xn−2 die ersten beiden Bits von X j+1 . Dann wird q j wie folgt bestimmt:

j+1
j+1

+1, falls xn−1 = 0 und xn−2 = 1
j+1
j+1
q j := 0,
falls xn−1 = xn−2


j+1
j+1
−1, falls xn−1 = 1 und xn−2 = 0
Mikroprogramm zur SRT-Division
Es wird nun ein Mikroprogramm für die SRT -Division angegeben. Hierzu seien folgende Bezeichnungen vereinbart:
• Register:
(DD, DE): Doppelt langer Dividend
DR : Divisor
5.4. Arithmetik bei redundanter Zahlendarstellung
DE : positive Quotientenbits
DH : negative Quotientenbits
Falls an der Stelle j kein Quotientenbit aufzunehmen ist, gilt DE j =
DH j = 0.
• Zähler:
Z (wie früher)
Das Mikroprogramm für nicht-negative Faktoren 0 ≤ W(DD, DE) < W(DR) < 1 lautet:
Mikroprogramm: SRT-Division
0 : [ (DD, DE ) := Dividend ; DR := Divisor ;
DH := 0; Z := n ]
1 : [ Z := Z - 1; q := -DDn−1 + DDn−2 ;
if DDn−1 6= DDn−2 then
if DDn−1 = 1 then
DD := DD + DR
else
DD := DD - DR ]
2 : [ (DE0 , DH0 ) :=
if q = 1 then
(1 ,0)
else
if q = -1 then
(0 ,1)
else
(0 ,0)
if Z > 0 then
shl ( DD, DE ); shl ( DH ); goto 1
else
shl ( DE ); shl ( DH ) ]
3 : DE := DE - DH
4 : Stop
In DH werden die negativen Quotientenbits als Einsen abgelegt. Daher kann im letzten Schritt subtrahiert werden, um das Ergebnis zu dekonvertieren.
127
128
Kapitel 5. Die Arithmetisch-Logische Einheit
Index
Überdeckung, 65, 66
Übertrag, 16, 81, 84, 122
1-Komplement, 15, 16
2-Komplement, 12, 15, 16, 19, 20, 83
3-Excess-Code, 24, 49
-typen, 33, 36
-wort, 29
Befehlsfolgezähler, 31
Befehlsregister, 4
Befehlssatz, 34
Befehlszählregister, 4, 45
Adder-Tree, 90, 92, 108, 109, 118, 119
Betrag+Vorzeichen, 11, 15, 102
Addierwerk, 82, 84, 91
Binär
Addition, 11, 15, 16, 79, 105, 107, 112,
-darstellung, 30
122, 124
-system, 10
serielle, 84, 87
-zahl, 11, 14, 84, 102
Additionsmethode, 79
Bitfehler, 27
Adresscodierung, 29
Bitfolge, 29
Adresse, 4, 35, 37
Bitstring, 22
Adressmatrix, 89
Boolesche Algebra, 52, 56
Adressmodifikation, 37
Boolescher Ausdruck, 58, 59, 62, 80, 82,
AEGP, 118, 120
83
Akkumulator, 4, 5, 29, 31, 33, 35
Booth
ALU, 79
Verfahren von, 106
AND, 50
Bus, 7, 8
ASCII-Code, 23
Assembler, 30
Carry, siehe Übertrag
Carry-Look-Ahead-Addierer, 94, 95, 99
Atom, 55
Aussagenkalkül, 52
Carry-Ripple-Addierer, 82, 93, 94
Axiomensystem, 52
Carry-Save-Addierer, 91
Carry-Skip-Addierer, 95, 96, 99
B+V-Codierung, siehe Betrag+Vorzeichen
n-Bit-, 98
Basis, 10, 122
zweiter Ordnung, 98
Basisadresse, 36
CISC, 34
Baustein, 49
Codewort, 9
-funktion, 50
Codierung, 9–11, 22, 25, 123
-system, 50
CSA, siehe Carry-Save-Addierer
BCD-Code, 24
Decodiermatrix, 89
Bedingungsmatrix, 89
Befehl, 2, 29
Dezimalsystem, 10
-ausführung, 29
Diodenmatrix, 88, 89
-strukturen, 30
Disjunktion, 83
129
130
Index
Disjunktive Normalform, 60
Dividend, 110, 114, 125
Division, 21, 79, 103, 111, 114–116, 122
iterative, 110
Non-Performing-, 111
Non-Restoring-, 112
serielle, 110
Divisionsrest, 111
Divisor, 110, 114, 125
DNF, siehe Disjunktive Normalform
Don’t Care, 48, 58, 65, 71
Earle Larch, 75
EBCDIC-Code, 23
einschlägiger Index, 59, 71
End-Around-Carry, 104
EQUIV, 50
Ergebnisparameterblöcke, 46
EXOR, 14, 50
FA, siehe Fulladder
Festkommadarstellung, 17
Fixpunkt, 115
Flipflop, 73
Fulladder, 80, 81, 83, 84, 90, 96
Gleitkommazahl, 18
Gray-Code, 24, 70
HA, siehe Halfadder
Halbaddierer, siehe Halfadder
Halfadder, 80, 81, 86, 90
Kosten, 82
Hamming-Distanz, 26
Hamming-Gewicht, 65
Hauptspeicher, 3
Hazards, 76
Hexadezimalsystem, 10
Hintergrundspeicher, 3
Huffman-Codierung, 23
IEEE-754-Format, 19
Implikant, 64
Indexregister, 4, 34
indirekte Adressierung, 37
Interrupt, 6
Iterationsvorschrift, 115–117, 119, 121
KNF, siehe Konjunktive Normalform
Kommunikationsnetz, 2
Komplementfreie Ringsummenentwicklung,
61
Komplementfunktion, 52
Konjunktion, 83
Konjunktive Normalform, 60
Korrekturbit, 106
Kostenfunktion, 63
Kostenmaß, 62
KRE, siehe Komplementfreie Ringsummenentwicklung
Längsparität, 26
Ladebefehl, 33
Leitung, 7
Linkageregister, 45
Linksshift, 21
Mantisse, 18, 19, 21
Maxterm, 56
Mengenalgebra, 52, 53
Mikro
-befehl, 88, 89
-operation, 88
-programm, 85, 87, 110
MIMD-Rechner, 5
Minimalpolynom, 64, 66, 81
Minimierungsproblem, 63
Minterm, 55, 58–60, 64, 65
MISD-Rechner, 5
Mnemonische Darstellung, 30
Monom, 64, 65
Multiplikand, 102, 103
Multiplikation, 21, 79, 102, 103, 108, 110,
115, 118, 119
serielle, 104, 105, 110
Multiplikationsmatrix, 103
Multiplikator, 102–106, 108
Multiplikatorcodierung, 106, 114, 118
Gruppengröße 1, 106
Multiplizierwerk, 115, 119
NAND, 74
Newton-Verfahren, 117
normalisierte Darstellung, 18, 19
normalisierte Gleitkommazahl, 117
Index
NOT, 50
Nullstelle, 115, 116
Objektcode, 30
Oktalsystem, 10
Opcode, 29, 30, 34
Operanden, 5, 30, 32
Operationen, 32, 34
Paralleladdierer, 82, 86
Paritätsbit, 25
Partialprodukt, 104, 106
Partialrest, 111, 114, 125
Pipelining, 90, 108, 119
PLA, siehe Programmable Logic Array
Postnormalisierung, 20, 21
Primimplikant, 64
wesentlich, 66
Programmable Logic Array, 88
Programmausführung, 30
Propagationskette, 84, 91
Prozessor, 1, 2
Pufferregister, 8
Pufferspeicher, 3
Quadratwurzel, 110, 119
Querparität, 26
Quine-McCluskey, 66
Quotient, 110, 111, 119
Quotientenbit, 111, 112, 125
Quotientenregister, 111
Rückkopplung, 74
Rückkopplungsleitung, 109
rationale Zahlen, 17
Recheneinheit, 1
Rechenoperationen, 11
Rechenwerk, 79
Rechnerbus, siehe Bus
Rechtsshift, 21, 120
Redundanz, 17
Redundanzziffern, 122
Register, 3
-befehl, 34
Allzweck-, 4
Befehls-, 4
Rekursion, 43
131
Rekursionsformel, 83, 94
Resolutionsblock, 71
RISC, 34
RS-Flipflop, 73
Schaltfunktion, 48, 49, 54, 58, 60, 62, 71
Schaltkreis, 47, 62, 72
Schaltnetz, 72
Schaltung, 47, 48
Schaltwerk, 47, 71, 72
Schulmethode, 103, 110
SDNR-Darstellung, 123
Shiftbefehl, 33
SIMD-Rechner, 5
SISD-Rechner, 4
Speicher, 2, 35
-adressierung, 29
-adressregister, 4
-datenregister, 4
Speicherelement, 72
Speicherzellen, 3
Stack, 29–32, 45
-befehl, 31
Stellenwert, 10
-codierung, 10, 79
-form, 122
Steuereinheit, 1
Steuermatrix, 89
Stone
Satz von, 52
Subtraktion, 11, 16, 83, 87, 105
Supergruppe, 98
Table-Look-Up, 114, 117
Takt, 71, 73, 75, 85, 88, 90, 92
Taktflanke, 76
Taktmatrix, 89
Torschaltung, 74, 101
Umschaltsymbol, 22
Unibus, siehe Bus
Unterprogramm, 29, 42, 44
-aufruf, 43
-bibliothek, 42
Vektoroperation, 30
Volladdierer, siehe Fulladder
132
Index
Von-Neumann
-Addition, 86, 123
-Adierer, 89
-Prinzip, 4, 5
Vorzeichenbit, 10, 11, 13, 16, 17
Wallace Tree, siehe Adder-Tree
Zahlenbereich, 11–13, 17
Zahlensystem, 10
Zahlenverlängerung, 14, 16
Herunterladen