Die Architektur der Rechenmaschinen
Z1 und Z3

Raúl Rojas

14. August 2000
Zusammenfassung

Dieses Kapitel bietet eine detaillierte Beschreibung der Architektur der Rechenmaschinen Z1 und Z3, die zwischen 1936 und 1941 von Konrad Zuse entworfen wurden. Die notwendigen Informationen wurden einer umfassenden Auswertung der von Zuse 1941 eingereichten und in diesem Band erstmalig gedruckten Patentanmeldung entnommen. Zusätzliche Erkenntnisse brachte eine Softwareemulation der Z3. Die Z1 wurde ausschließlich mit mechanischen Komponenten gebaut, die Z3 benutzte elektromagnetische Relais. Beide Maschinen hatten jedoch eine gemeinsame logische Struktur und das Programmiermodell war identisch. Es wird gezeigt, daß die Z1 und die Z3 Eigenschaften besaßen, die in heutigen Computern selbstverständlich sind: Speicher und Prozessor waren getrennte Einheiten, der Prozessor konnte Gleitkommazahlen bearbeiten und beherrschte die vier arithmetischen Grundrechenarten ebenso wie die Quadratwurzelberechnung. Das Programm wurde auf einem Lochstreifen gespeichert und sequentiell gelesen. Durch die Analyse der Architektur der Z1 und Z3 vermittelt dieses Kapitel das notwendige Hintergrundwissen für ein leichteres und effektiveres Verständnis der Patentanmeldung der Z3.

1 Frühe Rechenmaschinen

Konrad Zuse wird in Deutschland gemeinhin als der Vater des Computers angesehen und seine Z1, ein zwischen 1936 und 1938 gebauter programmierbarer Automat, wird hierzulande oft als der erste Computer der Welt bezeichnet. Andere Nationen reklamieren dieses Privileg für einen ihrer eigenen Wissenschaftler, und es hat lange und oft bittere Debatten über den „wahren“ Erfinder des Computers gegeben. Manchmal wird der Anspruch des „ersten“ Computers durch weitere, die technischen Eigenschaften betreffende Attribute eingeschränkt (wobei dann aber gerne genau diese Eigenschaften als die eigentlich wichtigen hingestellt werden). Der ENIAC (Akronym für Electronic Numerical Integrator and Computer) ist zum Beispiel als der erste allgemeine, großformatige, elektronische Computer der Welt bezeichnet worden.1 Diese Maschine wurde an der Moore School of Electrical Engineering an der Universität von Pennsylvania von Mai 1943 bis 1945 gebaut. Der ENIAC löste sein erstes Problem im Dezember 1945 und wurde im Februar 1946 offiziell eingeweiht.

Ein weiterer Anwärter auf den Titel des ersten Computers ist der Mark I, der von Howard Aiken an der Harvard Universität zwischen 1939 und 1944 gebaut wurde. Der Mark I war eine elektromechanische Maschine, d. h. er war nicht total mechanisch wie frühere Rechenautomaten, verwendete aber auch nicht die damals bereits verfügbaren elektronischen Komponenten.2 Die Maschine von John Atanasoff (die später ABC genannt wurde), gebaut zwischen 1938 und 1942 am Iowa State College, benutzte Vakuumröhren, konnte aber nur Vektoren addieren und subtrahieren und hatte nicht die für allgemeine Berechnungen notwendige minimale Struktur.3 Im direkten Gegensatz zu dieser Maschine waren Z1 und Z3 weit flexibler; sie konnten eine lange Folge von Befehlen ausführen, die auf einem Lochstreifen gestanzt war. Die Maschinen von Zuse waren mechanisch oder elektromechanisch und von kleineren Abmessungen. Weil die Z1 vor dem Mark I fertiggestellt wurde, wird sie als die erste programmierbare vollautomatische Rechenmaschine der Welt bezeichnet. Natürlich kann die alte Debatte mit einem einzigen Artikel nicht beendet werden, es wird jedoch in den nächsten Abschnitten gezeigt, wie fortschrittlich die Maschinen von Zuse aus dem Blickwinkel der modernen Computerarchitektur waren und wie gut sie im direkten Vergleich mit anderen Entwürfen ihrer Zeit abschneiden.

In den dreißiger Jahren fing Konrad Zuse noch als Student an, über Rechenmaschinen nachzudenken. Er erkannte, daß er in der Lage war, einen Automaten zu konstruieren, der Folgen von arithmetischen Operationen ausführen konnte, wie sie zur Durchführung ingenieurmäßiger Berechnungen notwendig sind. Als Bauingenieur hatte er keine Ausbildung in Elektrotechnik oder Elektronik erhalten und war auch nicht mit der Technik vertraut, die in konventionellen mechanischen Rechnern benutzt wurde. Dieses nominelle Defizit zahlte sich jedoch zu seinem Vorteil aus, denn er mußte das ganze Problem der arithmetischen Berechnungen überdenken und kam so zu neuen Lösungen.

Zuse entschied sich, eine erste experimentelle Rechenmaschine zu bauen, die zwei wesentliche Ideen umsetzte: a) Die Maschine arbeitete mit binären Zahlen; b) Rechen- und Steuereinheiten wurden vom Speicher getrennt. Jahre bevor John von Neumann die Vorteile einer Computerarchitektur schriftlich begründete, in der Prozessor und Speicher getrennt sind, war Zuse bereits auf den gleichen Gedanken gekommen. Es ist jedoch anzumerken, daß diese Idee auf Charles Babbage zurückgeht, der im vorigen Jahrhundert beim Entwurf der Analytischen Maschine zum selben Konstruktionsprinzip kam. Im Jahr 1936 wurde der Speicher4 der von Zuse geplanten Maschine fertiggestellt. Es war ein mechanisches Gerät, aber nicht vom üblichen Typ. Zuse implementierte logische und arithmetische Operationen mit gestanzten Blechschienen anstelle von Zahnrädern (wie sie von Babbage benutzt wurden). Die Blechschienen konnten sich nur in zwei Richtungen bewegen (vorwärts und rückwärts) und waren deswegen ausreichend für eine binär arbeitende Maschine.5 Der Prozessor der Z1 wurde einige Monate nach dem Speicher fertiggestellt und verwendete die gleiche Art von Technik für die einzelnen Komponenten. Er arbeitete mit dem Speicher zusammen, war aber nicht sehr zuverlässig. Das Hauptproblem bestand in der präzisen Synchronisation, die gebraucht wurde, um übermäßige mechanische Beanspruchungen der bewegenden Teile zu vermeiden. Es ist interessant anzumerken, daß im gleichen Jahr, als der Speicher der Z1 fertig wurde, Alan Turing seinen bahnbrechenden Artikel über berechenbare Zahlen schrieb, in dem er das intuitive Konzept von Berechenbarkeit formalisierte.

Obgleich die Z1 unzuverlässig blieb, zeigte sich, daß der Entwurf konsistent war, und dies trieb Zuse dazu, andere mögliche Realisierungen zu erforschen. Er entschied sich für elektromechanische Relais, die vor und während des Zweiten Weltkrieges billiger und leichter als andere Komponenten zu erhalten waren. Ein Versuchsmodell (später Z2 genannt) verwendete einen Prozessor, bestehend aus Relais, und den mechanischen Speicher der Z1. Bald danach fing Zuse an, die Z3 zu bauen, die ausschließlich aus Relais bestand, aber die gleiche logische Struktur wie die Z1 besaß. Die Z3 war 1941 fertig und einsatzbereit, vier Jahre vor der ENIAC.

Dieses Kapitel bietet eine detaillierte Darstellung der gemeinsamen Architektur von Z1 und Z3. Die Z1 wurde von Zuse selbst in den achtziger Jahren in Berlin rekonstruiert und ist nun eine der Ausstellungsattraktionen des Deutschen Technikmuseums in Berlin. Jedoch beschreiben die bisher verfügbaren Informationen nur den Entwurf des mechanischen Speichers.6 Die Z3 wurde von Zuse in der Patentanmeldung Z391 von 1941 dokumentiert (ab Seite ?? in diesem Band); diese ist wegen der nicht standardisierten Notation und Terminologie schwer zu durchschauen. Czaudernas Buch über die Z3 ist eine gute Quelle, um das historische Umfeld von Zuses Erfindung zu verstehen, beschreibt aber die Z3 nicht im Detail.7 Im folgenden wird nur auf die Z3 eingegangen, weil sie logisch und funktional praktisch mit der Z1 äquivalent ist. Der maßgebliche Unterschied in der Architektur von Z1 und Z3 besteht in der Tatsache, daß die Quadratwurzeloperation in der Z1 fehlte. Es gab außerdem unwesentliche Unterschiede in der Anzahl der Bits, die der Prozessor für arithmetische Operationen benutzte (die Z1 verwendete ein Bit weniger für die Mantisse von Gleitkommazahlen) und in der Anzahl der Zyklen, die für jeden Befehl benötigt wurden. Gleichwohl kann die Z1 im Hinblick auf ihre architektonischen Eigenschaften als Äquivalent der Z3 betrachtet werden. Für die Schaltungen beider Maschinen entwickelte Zuse dann auch eine einheitliche Beschreibung („abstrakte Schaltgliedtechnik“8).

2 Überblick über die Architektur von Z1 und Z3

Dieser Abschnitt faßt die wichtigsten architektonischen Eigenschaften der Z3 zusammen. Die Darstellung bewegt sich vom Einfachen zum Komplexen: zuerst wird ein Überblick gegeben und in Abschnitt 3 werden dann die Details besprochen. Um einen einfachen Satzbau zu ermöglichen, wird von der Z3 im Präsens gesprochen.

2.1 Struktureller Aufbau

Die Z3 ist eine Maschine, die Gleitkommazahlen verarbeitet. Während die anderen damaligen Rechenautomaten wie der Mark I, der ABC und der ENIAC mit Festkommazahlen arbeiteten, hatte Zuse sich bereits viel früher dafür entschieden, die „halblogarithmische“ Notation zu verwenden. Diese entspricht der modernen Darstellung von numerischen Größen als Gleitkommazahlen.


PIC

Abbildung 1 Die Bausteine der Z3

Abbildung 1 zeigt einen Überblick der Grundstruktur der Z3. Das erste relevante Merkmal ist die Trennung von Prozessor und Speicher. Die Z3 besteht aus einem binären Speicher (mit einem nominellen Speichervermögen von 64 Gleitkommazahlen), einem binären Gleitkommazahlprozessor, einer Steuereinheit sowie Ein- und Ausgabegeräten. Speicher und arithmetische Einheit sind über einen Datenbus verbunden, der Exponent und Mantisse der Gleitkommazahldarstellung überträgt. Die Steuereinheit enthält für jeden Befehl einen Mikrosequenzer. Signalleitungen, die von der Steuereinheit zum Prozessor, dem Speicher und den Ein- bzw. Ausgabegeräten gehen, sorgen für die richtige Synchronisation aller Geräte. Der Lochstreifenleser liefert den Befehlscode für jeden Befehl ebenso wie die Adresse für Speicherzugriffe. Die Ein- bzw. Ausgabegeräte sind durch den Datenbus mit der Recheneinheit verbunden.

2.2 Darstellung von Gleitkommazahlen

Abbildung 2 zeigt die Darstellung der Gleitkommazahlen im Speicher der Z3. Das erste Bit wird benutzt, um das Vorzeichen der Zahl zu speichern, die folgenden 7 Bits sind für den Exponenten und die letzten 14 Bits für die Mantisse reserviert (nur die 14 Stellen rechts vom Dezimalpunkt). Die Bits des Exponenten werden „Teil A“ der Zahl genannt und als a6, ..., a0 bezeichnet. Die Bits der Mantisse werden „Teil B“ genannt und als b0, b-1, ..., b-14 geschrieben. Der Exponent ist eine Zahl im Zweierkomplement. Der Bereich des Exponenten reicht deswegen von -64 bis 63. Die Mantisse wird in normalisierter Form gespeichert, das heißt, die erste Ziffer vor dem Dezimalpunkt (b0) muß immer eine 1 sein. Diese Ziffer braucht nicht gespeichert zu werden (und erscheint deswegen nicht in Abb. 2), so daß der effektive Zahlenbereich im Speicher äquivalent zu einer Mantisse von 15 Bits ist. Das einzige Problem mit der normalisierten Mantisse ist, daß damit die Zahl Null nicht dargestellt werden kann. Die Z3 benutzt die Konvention, daß jede Mantisse mit dem Exponenten -64 als Null zu interpretieren ist. Außerdem gilt jede Zahl mit dem Exponenten 63 als die Zahl „Unendlich“. Operationen mit Null oder Unendlich werden als Ausnahmen behandelt. Eine spezielle Hardware überwacht jede in den Prozessor eingelesene Zahl, um die Ausnahmebits (siehe Abschnitt 4) zu setzen.


PIC

Abbildung 2 Die Darstellung von Gleitkommazahlen im Speicher

Mit dieser Konvention ist die kleinste darstellbare positive Zahl im Speicher der Z3 die Zahl 2-63  ~~ 1.08 × 10-19 und die größte ist 1, 9999 × 262  ~~ 9.22 × 1018. Die Argumente für Berechnungen können als Dezimalzahlen (vier Ziffern) auf der Tastatur der Z3 eingegeben werden. Der Exponent der dezimalen Darstellung wird durch Drücken der entsprechenden Position in einer mit -8, -7, ..., 7, 8 beschrifteten Reihe von Tasten eingegeben (die ursprüngliche Z3 konnte also lediglich Eingaben zwischen 1 × 10-8 und 9999 × 108 annehmen). Die Z3 kann das vom Programm produzierte numerische Ergebnis nicht drucken. Statt dessen wird eine einzelne Zahl mit einer Matrix von Lampen angezeigt, die die Ziffern 0 bis 9 darstellen. Die größte darstellbare Dezimalzahl ist 19999 und die kleinste 00001. Der größte Exponent, der angezeigt werden kann, ist +8, der kleinste -8. Die Rekonstruktion der Z3 in München benutzt für die Ausgabe des Exponenten einen größeren Ausgabebereich (-12 bis +12).

2.3 Befehlssatz

Das Programm für die Z3 befindet sich auf einem Lochstreifen. Die acht Bits in jeder Zeile codieren einen Befehl. Der Befehlssatz der Z3 besteht aus den neun in Tabelle 1 aufgelisteten Befehlen. Es gibt drei Klassen davon: Ein-/Ausgabe-, Speicher- und Arithmetikbefehle. Der Befehlscode hat eine variable Länge von zwei bis fünf Bits. Speicheroperationen beinhalten die Adresse eines Speicherwortes in den niederwertigen sechs Bits, d. h. der Adreßraum hat wie bereits erwähnt eine nominelle maximale Größe von 64 Worten.



Tabelle 1 Befehlssatz und Befehlscodes der Z3
Klasse BefehlBeschreibung Befehlscode
Ein-/AusgabeLu Lesen von Tastatur 01 110000
Ld Ergebnis anzeigen 01 111000
Speicher P r z Lesen von Adresse z 11 z6z5z4z3z2z1
P s z Speichern in Adresse z10 z6z5z4z3z2z1
Arithmetik Lm Multiplikation 01 001000
Li Division 01 010000
Lw Quadratwurzel 01 011000
Ls1 Addition 01 100000
Ls2 Subtraktion 01 101000

Die Befehle können in beliebiger Reihenfolge kombiniert werden. Die Befehle Lu und Ld (Lesen von Tastatur, Anzeige des Ergebnisses) halten die Maschine an, so daß der Bediener genügend Zeit hat, um eine Zahl einzugeben oder das Ergebnis aufzuschreiben. Die Maschine wird dann neu gestartet und setzt die Ausführung des Programms fort.

Die offensichtlichste Lücke im Befehlssatz der Z3 ist das Nichtvorhandensein von Verzweigungen. Eine Schleife kann einfach durch das Zusammenkleben der beiden Enden eines Lochstreifens realisiert werden, aber es gibt keine Möglichkeit zur Implementierung von bedingten Sprüngen in Befehlsfolgen. Schon aus diesem Grund kann man die Z3 nicht als einen Universalrechner im Sinne von Turing einstufen.9

2.4 Anzahl der Zyklen

Die Z3 ist eine getaktete Maschine. Jeder Takt (in der Terminologie von Zuse ein „Spiel“) ist in die fünf römisch numerierten „Schritte“ bzw. „Stufen“ I, II, III, IV und V unterteilt. Der momentane Befehl auf dem Lochstreifen wird in Stufe I eines Zyklus decodiert. Die zwei grundlegenden arithmetischen Operationen der Maschine sind Addition und Subtraktion von Exponent und Mantisse. Diese Operationen können in den ersten drei Stufen eines jeden Zyklus ausgeführt werden. Die Stufen IV und V werden benutzt, um die Argumente für die nächste Operation vorzubereiten oder um ein Ergebnis in die Register oder in den Speicher zurückzuschreiben.

Die in der Z3 implementierten Befehle benötigen die folgende Anzahl von Zyklen:
  Multiplikation:       16 Zyklen
Division: 18 Zyklen
Quadratwurzel: 20 Zyklen
Addition: 3 Zyklen
Subtraktion: 4 oder 5 Zyklen (je nach Ergebnis)
Lesen von Tastatur (Eingabe): 9 bis 41 Zyklen (je nach Exponent)
Ergebnis anzeigen (Ausgabe): 9 bis 41 Zyklen (je nach Exponent)
Lesen aus Speicher: 1 Zyklus
Schreiben in Speicher: 0 Zyklen (!)
Nach Aussage von Zuse wurden für eine Multiplikation drei Sekunden benötigt. Da eine Multiplikation 16 Zyklen braucht, können wir annehmen, daß die Z3 eine Taktfrequenz von (16/3)  ~~ 5.33 Hz erreicht hat.

Die Anzahl der Zyklen für Ein- und Ausgabebefehle ist variabel, da sie vom Exponenten der Argumente abhängig ist. Da die Eingabe von der Dezimal- in die Binärdarstellung umgewandelt werden muß, wird die Anzahl der Multiplikationen, die mit dem Faktor 10 oder 0,1 benötigt werden, vom dezimalen Exponenten bestimmt (siehe auch Abschnitt 4).

Addition und Subtraktion benötigen mehr als einen Zyklus, da im Falle von Gleitkommazahlen der Exponent von beiden Argumenten vereinheitlicht werden muß. Dies erfordert einige zusätzliche Vergleiche und Verschiebungen.

Eine Zahl kann in null Zyklen in den Speicher geschrieben werden, weil das Ergebnis der letzten arithmetischen Operation auf die gewünschte Speicheradresse umgeleitet wird. Der für das Speichern benötigte Zyklus überlappt sich mit dem letzten Zyklus der arithmetischen Operation. Nach dem Speicherbefehl werden die Register des Prozessors gelöscht. Es ist zu beachten, daß zwei Speicherbefehle unmittelbar hintereinander unsinnig sind, da nur der erste das Resultat der letzten arithmetischen Operation auf dem Bus findet.

2.5 Programmiermodell

Es ist sehr wichtig, das Programmiermodell, d. h. die für den Programmierer abstrakt vorhandenen Bestandteile der Maschine, zu beschreiben. Vom Standpunkt der Software besteht die Z3 aus 64 Speicherworten, die in zwei Gleitkommaregister (bezeichnen wir sie einfach mit R1 und R2) geladen werden können.10 Diese zwei Register beinhalten die beiden Argumente für arithmetische Operationen. Der Programmierer kann eine beliebige Folge von Befehlen schreiben, aber er muß dabei den Zustand der Register im Auge behalten.

Vor allem muß der folgende Punkt beachtet werden: Die erste Speicher-Leseoperation in einem Programm (P r z) oder die erste Eingabeoperation (Lu) überträgt den Inhalt der Adresse z bzw. die über die Tastatur eingegebene Zahl nach R1. Jede nachfolgende Eingabe- oder Speicher-Leseoperation überträgt eine Binärzahl nach R2.

Die Argumente für arithmetische Operationen sind im Befehlscode nicht explizit angegeben. Ihre implizite Semantik ist die folgende:
      Multiplikation:   R1:=R1×R2
Division: R1:=R1/R2
Addition: R1:=R1+R2
Subtraktion: R1:=R1-R2
Quadratwurzel:R1:= V~ R1-
R2 wird nach jeder arithmetischen Operation auf 0 gesetzt, während das Ergebnis in R1 gespeichert wird. Die Ausgabe des Ergebnisses bezieht sich immer auf R1. Nach einem Speicher- oder Ausgabebefehl wird R1 gelöscht. Die nächste Leseoperation bezieht sich dann wieder auf R1.

An dieser Stelle ist ein Beispiel besser als weitere Erklärungen, um das Programmiermodell der Z3 zu verdeutlichen. Nehmen wir an, wir wollen ein Polynom nach der Methode von Horner berechnen:

((a4x + a3)x + a2)x + a1

Nehmen wir weiterhin an, daß die Konstanten a4, a3, a2 und a1 in den Adressen 4, 3, 2 bzw. 1 gespeichert sind. Die Zahl x ist in der Adresse 5 gespeichert. Das Programm für die gewünschte Berechnung lautet:
P r 4 Lade a4 in R1
P r 5 Lade x in R2
Lm Multipliziere R1 und R2, Ergebnis in R1
P r 3 Lade a3 in R2
Ls1 Addiere R1 und R2, Ergebnis in R1
P r 5 Lade x in R2
Lm Multipliziere R1 und R2, Ergebnis in R1
P r 2 Lade a2 in R2
Ls1 Addiere R1 und R2, Ergebnis in R1
P r 5 Lade x in R2
Lm Multipliziere R1 und R2, Ergebnis in R1
P r 1 Lade a1 in R2
Ls1 Addiere R1 und R2, Ergebnis in R1
Ld Ausgabe des Ergebnisses
Nach der Ausführung des letzten Befehls hält der Prozessor an. Ein neues Programm kann gestartet werden.

3 Blockdiagramm der Z3

In diesem Abschnitt beschäftigen wir uns eingehend mit der Struktur der Z3 und beschreiben detailliert ihre wesentlichen Bausteine. Der wichtigste Punkt betrifft die Sicherstellung der richtigen Synchronisation der verfügbaren Komponenten.

3.1 Die arithmetische Einheit

Abbildung 3 zeigt eine vereinfachte Darstellung der arithmetischen Einheit der Z3. Es gibt zwei Teile: Die linke Seite wird für Operationen mit den Exponenten von Gleitkommazahlen benutzt, die rechte Seite für Operationen mit den Mantissen. Af und Bf sind Register, die jeweils für die Speicherung von Exponent und Mantisse derselben Gleitkommazahl benutzt werden. Dies ist aus Sicht des Programmierers das Register R1. Im folgenden wird deswegen auf R1 als Registerpaar <Af,Bf> Bezug genommen. Das Registerpaar <Ab,Bb> speichert Exponent und Mantisse von Register R2 des Programmiermodells. Das Paar <Aa,Ba> enthält den Exponenten und die Mantisse eines temporären dritten Gleitkommazahlregisters, das dem Programmierer verborgen bleibt. Die beiden Addierer A und B werden jeweils für die Addition und die Subtraktion von Exponenten und Mantissen benutzt. Das Ergebnis für den Exponentenanteil einer Operation wird in Ae abgelegt. Für den Mantissenanteil wird das Ergebnis in Be abgelegt. In Teil B erlaubt ein Multiplexer statt der Ausgabe des Addierers direkt das Register Ba nach Be durchzuschalten. Der Multiplexer wird vom Relais Bt gesteuert (wenn Bt=0, dann wird Ba nach Be übertragen).


PIC

Abbildung 3 Register und Rechenwerk

Die kleinen mit Ea, Eb, Ec, Ed, Ef, F a, F b, F c, F d und Ff beschrifteten Kästchen stellen Relaisschalter dar, die den Datenbus öffnen oder schließen. Wenn zum Beispiel der Inhalt von Register Af ins Register Aa übertragen werden soll, dann wird der Relaisschalter Ea auf 1 gesetzt mit der Wirkung Aa:=Af. Wie im Diagramm zu erkennen ist, kann der Inhalt von Af dem Zustand der Relaisschalter entsprechend nach Aa oder Ab übertragen werden. Der Inhalt von Ae kann nach Aa, Ab oder Af übertragen werden. Die Struktur von Teil B der arithmetischen Einheit ist derjenigen von Teil A sehr ähnlich, aber zusätzlich zum von Bt kontrollierten Multiplexer gibt es einen Shifter zwischen Bf und Ba und einen weiteren zwischen Bf und Bb. Der erste Shifter kann die Mantisse um bis zu zwei Stellen nach rechts oder um eine Stelle nach links verschieben. Dies bedeutet entweder eine Division durch 4 oder eine Multiplikation mit 2. Der zweite Shifter kann die Mantisse in Bf zwischen einer und 15 Stellen nach links sowie zwischen einer und 16 Stellen nach rechts verschieben. Diese Verschiebungen sind für die Addition und die Subtraktion von Gleitkommazahlen notwendig. Multiplikation und Division mit Potenzen von 2 sind auf diese Weise ohne Zeitverlust - während die Operanden für die nächste arithmetische Operation geholt werden - durchzuführen.

Die Bitlängen der Register sind folgende:
      Af 7 Bits Bf 17 Bits
Aa 8 Ba 19
Ab 8 Bb 18
Ae 8 Be 18
Wie aus dieser Liste ersichtlich ist, benutzen Aa, Ab und Ae ein extra Bit, um die Addition der Exponenten zu bearbeiten. Teil B des Prozessors benutzt zwei extra Bits für die Mantissenanteile (b-15, b-16) und verwendet explizit Bit b0, das nicht gespeichert wird. Die extra Bits an den Positionen -15 und -16 erlauben es, die Genauigkeit der Berechnung zu erhöhen. Damit beträgt die Anzahl der Bits, die für das Speichern des Ergebnisses einer arithmetischen Operation im Register Bf gebraucht werden, siebzehn. Register Ba und Bb benötigen weitere extra Bits (ba2, ba1, und bb1), um die Zwischenergebnisse einiger numerischer Algorithmen aufnehmen zu können. Insbesondere der Quadratwurzelalgorithmus kann in Ba zu Teilberechnungen führen, die bis zu drei Einsen links vom Dezimalpunkt enthalten.

Die wesentlichen primitiven Operationen in diesem Kreislauf sind Addition und Subtraktion von Exponenten und Mantissen. Falls das Relais As (Bs) gesetzt ist, wird der Negativwert des zweiten Arguments Ab (Bb) in den Addierer geladen. Der Addierer in Teil A subtrahiert also die Argumente, wenn das Relais As auf 1 gesetzt ist, ansonsten werden die Argumente addiert. Das gleiche gilt für den Teil B und das Relais Bs. Die in der Abbildung dargestellte Konstante 1 wird gebraucht, um das Zweierkomplement einer Zahl zu erzeugen.

Nehmen wir an, daß zwei Zahlen mit dem gleichen Exponenten addiert werden sollen. Der erste Exponent wird in Af gespeichert, der zweite in Ab. In Teil A der Maschine muß keine besondere Aktion getätigt werden, weil beide Exponenten gleich sind. In Teil B wird die Mantisse der ersten Zahl in Bf gespeichert und die Mantisse der zweiten in Bb. Der erste Schritt besteht darin, Ba mit Bf zu laden, indem der Relaisschalter F a auf 1 gesetzt wird. Die Addition wird als nächstes ausgeführt, das Relais Bt wird auf 1 gesetzt und damit Be das Ergebnis Ba+Bb zugewiesen. Der Relaisschalter Ff wird nun auf 1 gesetzt und das Ergebnis in Bf gespeichert. Wie zu sehen ist, kann die Information zwischen den Registern bewegt werden und läuft damit in einem Kreislauf. Der Computerarchitekt muß die richtige Konfiguration der Relaisschalter bereitstellen, um die gewünschte Operation zu erhalten. Dies wird in der Z3 mit einer Technik bewerkstelligt, die der Mikroprogrammierung sehr ähnlich ist.

3.2 Die Steuereinheit

Abbildung 4 zeigt ein Detaildiagramm der Steuereinheit und der Ein-/Ausgabeeinheiten. Die Steuereinheit bestimmt die richtige Mikrosequenzierung der Befehle. Es gibt spezielle Schaltkreise für jeden Befehl aus dem Befehlssatz. Der Schaltkreis Pa decodiert den Befehlscode des vom Lochstreifen gelesenen Befehls. Wenn es ein Speicherbefehl ist, setzt Pb den Adreßbus auf den Wert der niederwertigen sechs Bits des Befehlscodes.


PIC

Abbildung 4 Die Steuereinheit und die Ein-/Ausgabeeinheiten

Der Schaltkreis Z stellt die Tastatur dar, die für die Eingabe von Dezimalzahlen in die Maschine benutzt wird. Nur ein Schalter in jeder der vier Spalten kann aktiviert werden. Der Exponent wird im Schaltkreis K durch das Drücken einer der mit -8 bis 8 beschrifteten Tasten gesetzt. Die Ausgabeeinheit ist ähnlich der Eingabeeinheit, allerdings zeigen hier aufleuchtende Lampen die entsprechenden Dezimalziffern, den Exponenten der Zahl (Schaltkreis Q) und das Vorzeichen an. Zu beachten ist eine fünfte Ziffer für die Ausgabe, die bei der Z3 nur 1 oder 0 sein kann.

Wenn einmal eine Dezimalzahl eingegeben wurde, dann überträgt der Datenbus die Ziffern in das Register Ba, und eine komplexe Serie von Operationen wird gestartet. Die Dezimaleingabe muß in eine Binärzahl umgewandelt werden. Dies bedeutet eine Reihe von Multiplikationen, deren Anzahl proportional zum absoluten Wert des Exponenten ist. Für den Exponenten 0 braucht die ganze Umwandlung 9 Zyklen. Für den Exponenten -8 sind jedoch 9 + 4 × 8 = 41 Zyklen notwendig.

3.3 Mikroprogrammsteuerung der Z3

Das Herz der Steuereinheit sind Mikrosequenzer. Bevor ihre Arbeitsweise beschrieben wird, ist es nötig, einen Blick auf die Verkettung von arithmetischen Befehlen in der Z3 zu werfen. Abbildung 5 zeigt die Grundidee. Jeder Zyklus in der Z3 wird in 5 Stufen aufgeteilt. Die Stufen IV und V werden benutzt, um Information von einem Teil der Maschine zu einem anderen zu übertragen. Während der Stufen I, II und III wird eine Addition oder Subtraktion im Teil A und eine andere im Teil B der Z3 ausgeführt. Wir bezeichnen dies als die „Ausführungsphase“ des Befehls. Ein typischer Befehl holt seine Argumente, führt eine Operation aus und schreibt das Ergebnis zurück. Zuse hat großen Wert darauf gelegt, Ausführungszeit dadurch zu sparen, daß die Argumentevorbereitungsphase des nachfolgenden Befehls mit der Ergebnissicherungsphase des gegenwärtigen Befehls überlappt wird. Wir können uns dies vorstellen als einen Befehlsausführungszyklus, der aus lediglich zwei Phasen besteht, wie in Abb. 5 zu sehen ist, in dem die ersten beiden Zyklen einer Reihe von Befehlen dargestellt werden. Diese Konvention wurde in den Tabellen über die numerischen Algorithmen übernommen, die weiter unten diskutiert werden.


PIC

Abbildung 5 Die Ausführungspipeline der Z3

Die Mikrosequenzierung erfolgt durch spezielle Schrittschalter (Zuse nannte sie „Steuerschalter“). Es gibt einen für den Multiplikationsalgorithmus, einen anderen für die Division und einen weiteren für die Quadratwurzeloperation. Der in Abb. 6 gezeigte bewegliche Arm fängt an, sich im Uhrzeigersinn zu bewegen, sobald die Steuereinheit den entsprechenden Befehl decodiert. In jedem Zyklus bewegt sich der Arm von einer Position zur nächsten. Der Arm steht unter elektrischer Spannung und aktiviert die Schaltkreise, mit denen er in Berührung kommt. In dem in der Abbildung gezeigten Beispiel setzt der bewegte Arm den Relaisschalter Ea auf 1 im ersten Zyklus. Dies führt zur Übertragung des Inhalts von Register Af nach Aa. Im nächsten Zyklus werden die Relaisschalter Ec und F c aktiviert. Auf diese Weise werden die Ergebnisse der Operation in den Teil A und B der Maschine in die Register Aa bzw. Bb zurückgeschrieben. Wie man leicht sehen kann, bietet ein derartiger Schrittschalter eine komfortable Plattform zur Veränderung der genauen Folge von Schaltereignissen für eine Operation. Die Schrittschalter entsprechen den Mikrosequenzern, die in heutigen Mikroprozessoren benutzt werden. Ich möchte dies nicht als echte Mikroprogrammierung bezeichnen, da in diesem Fall die Mikrosequenzen fest verschaltet sind; es ist jedoch klar, daß Mikroprogrammierung und Mikrosequenzierung nahe miteinander verwandt sind.

PIC

Abbildung 6 Schrittschalter für die Mikrosequenzer

Die umfassende Nutzung der Mikrosequenzierung erlaubte es Zuse, die Z3 zu vereinfachen. Sobald die grundsätzlichen Schaltkreise entworfen waren, war es lediglich eine Frage der Verfeinerung der Steuerung, bis die optimalen Folgen von Schaltereignissen gefunden waren. Es gibt einige Details, die vom Programmierer beim Entwurf des „Mikroprogramms“ beachtet werden müssen, da sonst Kurzschlüsse die Hardware zerstören können. Die Z1 mit ihrem mechanischen Design war in diesem Sinne noch weit sensibler als die Z3. Auch nachdem sie fertiggestellt war, gab es Befehlsfolgen, die ein Programmierer vermeiden mußte, um die Hardware nicht zu beschädigen. Eine solche Befehlsfolge wurde versehentlich 1994 in der rekonstruierten Z1 des Deutschen Technikmuseums in Berlin gestartet und führte zu einer leichten Beschädigung der Maschine.

4 Arithmetische Algorithmen

In diesem Abschnitt werden die numerischen Algorithmen der Z1 und Z3 offengelegt und mit Hilfe von Steuerungsdiagrammen im Detail besprochen.

4.1 Übertrag bei der Addition

Ein wichtiger Aspekt der Z3 ist der Entwurf eines Addierers, der in der Lage ist, Additionen und Subtraktionen unter Nutzung der Technik des carry look-ahead zu berechnen. Wird die parallele binäre Addition direkt und ohne eine solche Optimierung implementiert, dann müssen Übertragbits von einer Bitposition zur nächsten weitergegeben werden. Für die Mantisse wären dann mindestens 16 Zyklen für die sichere Weitergabe der Übertragbits notwendig.

Die Addierer der Z3 sind viel schneller - sie leisten eine Addition oder eine Subtraktion in den Stufen I, II oder III eines einzigen Zyklus. Die Subtraktion wird durch Komplementierung des zweiten Argumentes und Addition einer zusätzlichen 1 auf der niederstwertigen Bitposition auf eine Addition reduziert.


PIC

Abbildung 7 Die Schaltung für carry look-ahead

Betrachten wir die Addition der Register Ba und Bb (Abb. 7). Wir werden im folgenden das i-te Bit von Register Bb mit bbi oder Bb[i] bezeichnen, je nachdem, welche Form bequemer ist. Die gleiche Notation wird für die anderen Register benutzt. Zuerst wird ein Zwischenergebnis berechnet, das die bitweise XOR-Operation auf beiden Registern darstellt, d. h. bci = (bai XOR bbi). Ein zweites Zwischenergebnis ist die bitweise AND-Operation, angewendet auf beide Register, i. e. bai AND bbi. Die nächste Operation betrifft die Ermittlung der Bitpositionen, für die ein Übertrag benötigt wird. Die Zwischenergebnisse bdi werden mit Hilfe der in Abb. 7 gezeigten Schaltung berechnet. Dabei ist zu beachten, daß, wenn ein Bit 1 ist, die entsprechende Leitung unter Spannung steht, ansonsten ist die Leitung von der Spannungsquelle getrennt (sog. three-state Schalter). Nur so kann die Arbeitsweise der Schaltung verstanden werden. Die Ruheposition der Relais bc1, ..., bc-16 ist in der Abbildung zu sehen. Falls Bit bci gleich 1 ist, wird das entsprechende Relais geschlossen. Das Endergebnis ist bei = bdi XOR bci. Es ist beachtlich, wie einfach die Benutzung der Relais die Verteilung des Übertrags bis zur letzten Bitposition macht. Der Übertrag wird beim Weitergeben von einer Position zur nächsten nicht verzögert, weil alle Relais gleichzeitig aktiviert werden.

Auch in der Z4 verwendete Zuse diese Schaltung. Eine weiter vereinfachte Relaisschaltung, die pro Stelle mit zwei Relais für Ba[i] und Bb[i] mit je vier Umschaltkontakten auskommt, geht auf Howard Aiken zurück.11 Die originale Z4 ist im Deutschen Museum in München ausgestellt.

Im folgenden werden die Algorithmen beschrieben, die bei Operationen mit Gleitkommazahlen in der Z3 benutzt werden. Sie sind ohne Ausnahme die gleichen wie sie heutzutage in einfachen Gleitkommaprozessoren verwendet werden.12

4.2 Ausnahmebedingungen bei Gleitkommazahlen

Das Problem mit Zuses Notation von Gleitkommazahlen ist, daß spezielle Konventionen für die Darstellung der Zahl Null angewendet werden müssen. Die Z3 löst dieses Problem und behandelt andere Ausnahmebedingungen (Überlauf, Unterlauf) durch die Überwachung des Wertes des Exponenten nach jeder arithmetischen Operation oder nach jedem Lesezugriff auf den Speicher. Eine spezielle Schaltung überprüft den Zustand von Bus Ae und fängt die Ausnahmebedingungen ab. Jede Zahl mit dem Exponenten -64 wird als Null betrachtet: Ein Relais (bezeichnet mit Nn1) wird auf 1 gesetzt, wenn die gelesene Zahl im Registerpaar <Af,Bf> gespeichert wird. Falls aber die gelesene Zahl im Registerpaar <Ab,Bb> gespeichert wird, dann wird das Relais Nn2 auf 1 gesetzt. Damit wissen wir jederzeit, ob ein oder beide Argumente einer arithmetischen Operation 0 sind. Etwas ähnliches wird für Exponenten mit dem Wert 63 gemacht (eine Zahl mit Wert Unendlich gemäß Zuses Konvention). In diesem Fall wird das Relais Ni1 oder Ni2 auf 1 gesetzt, je nachdem, in welchem Registerpaar die Zahl gespeichert wird.

Operationen, die eine „Ausnahmezahl“ (Null oder Unendlich) als Argument enthalten, werden wie üblich ausgeführt, aber das Ergebnis wird von der Überwachungsschaltung überschrieben. Sei zum Beispiel angenommen, daß eine Multiplikation berechnet wird und daß das erste Argument 0 ist (Nn1 wurde auf 1 gesetzt). Die Berechnung geht weiter wie üblich, aber in jedem Zyklus liefert die Überwachungsschaltung das Ergebnis -64 am Ausgang des Addierers im Teil A. Es ist unerheblich, welche Operation mit der Mantisse ausgeführt wird, weil der Exponent des Ergebnisses auf -64 gesetzt wird und damit das Endergebnis 0 ist. Die Division durch eine unendliche Zahl wird auf ähnliche Weise abgearbeitet. Die Z3 erkennt nichtdefinierte Operationen wie 0/0,  oo -  oo ,  oo / oo und 0 ×  oo . In allen diesen Fällen leuchtet ein passend beschriftetes Ausnahmelämpchen an der Ausgabeeinheit auf und die Maschine wird angehalten. Die Z3 produziert immer das richtige Ergebnis, wenn ein Argument 0 oder  oo ist und das andere Argument innerhalb der numerischen Grenzen liegt.13

Eine zusätzliche Schaltung überwacht den Exponenten am Ausgang des Exponentenaddierers. Falls der Exponent größer oder gleich 63 ist, dann ist ein Überlauf eingetreten und das Ergebnis muß auf  oo gesetzt werden. Falls der Exponent kleiner als -64 ist, dann ist ein Unterlauf eingetreten und das Ergebnis muß auf 0 gesetzt werden. Um dies zu erlauben, wird das entsprechende Relais (Nn1 oder Ni1) auf 1 gesetzt.

Es ist Zuse gelungen, eine Ausnahmebehandlung zu implementieren, die nur ein paar Relais benutzte. Diese Eigenschaft der Z3 ist wohl eine der elegantesten im ganzen Entwurf der Maschine. Viele der ersten Mikroprozessoren in den siebziger Jahren konnten keine Ausnahmebehandlungen bearbeiten und überließen dies der Software. Zuses Ansatz ist sinnvoller, denn er befreit den Programmierer von der Last der Prüfung auf numerische Grenzüberschreitungen vor jeder Operation.

4.3 Addition und Subtraktion

Um zwei Gleitkommazahlen x und y zu addieren oder zu subtrahieren, muß ihre Darstellung auf einen gemeinsamen Exponenten gebracht werden. Danach müssen nur noch die Mantissen addiert oder subtrahiert werden. Falls sich die Exponenten unterscheiden, muß die Mantisse der kleineren Zahl um entsprechend viele Stellen nach rechts verschoben werden und ihr Exponent entsprechend erhöht werden (um den Wert der Zahl unverändert zu lassen), bis beide Exponenten gleich sind. Nach 17 Verschiebungen nach rechts wird die kleinere Zahl Null. Deswegen wird eine Mantisse maximal um 16 Stellen nach rechts geshiftet.


Zyklus Stufe Exponent Mantisse
0 I,II,III
1 IV,V
Aa:=Af
I,II,III
Ae:=Aa-Ab
Be:=0+Bb
2 IV,V
wenn (Ae>0)
dann Ab:=0, Aa:=Af
sonst Aa:=0
wenn (Ae>0)
dann Ba:=Bf, Bb:=Be (verschoben)
sonst Ba:=Be, Bb:=Bf (verschoben)
(Be oder Bf werden |Ae| Stellen
nach rechts verschoben)
I,II,III
wenn (Be>2)
dann Ae:=Aa+Ab+1
sonst Ae:=Aa+Ab
Be:=Ba+Bb
3 IV,V
Af:=Ae
wenn (Be>2)
dann Bf:=Be/2
sonst Bf:=Be
Abbildung 8 Die drei Zyklen, die für eine Addition gebraucht werden. Die Argumente für die Addition werden in den Registerpaaren <Af,Bf> und <Ab,Bb> gespeichert, bevor die Operation ausgeführt wird. Aa und Ba sind am Anfang Null.


Zyklus Stufe Exponent Mantisse
0 I,II,III
1 IV,V
Aa:=Af
I,II,III
Ae:=Aa-Ab
Be:=0+Bb
2 IV,V
wenn (Ae>0)
dann Ab:=0, Aa:=Af
sonst Aa:=0
wenn (Ae>0)
dann Ba:=Af, Bb:=Be (verschoben)
sonst Ba:=Be, Bb:=Bf (verschoben)
(Be oder Bf werden |Ae| Stellen
nach rechts verschoben)
I,II,III
Ae:=Aa+Ab
Be:=Ba-Bb
3 IV,V
Aa:=Ae, Ab:=0
Ba:=0, Bb:=Be
I,II,III
Ae:=Aa+Ab
Be:=Ba-Bb
4 IV,V
Aa:=Ae
Ab:=Anzahl der
Verschiebungen
Bb:=Be (verschoben)
(Be wird durch Verschiebung
nach links normalisiert)
I,II,III
Ae:=Aa-Ab
Be:=0+Bb
5 IV,V
Af:=Ae
Bf:=Be
Abbildung 9 Die vier bzw. fünf Zyklen, die für eine Subtraktion gebraucht werden. Die Argumente für die Subtraktion werden in den Registerpaaren <Af,Bf> und <Ab,Bb> gespeichert, bevor die Operation ausgeführt wird. Aa und Ba sind am Anfang Null. Zyklus 3 wird nur dann ausgeführt, wenn die Differenz der Mantissen negativ ist.

Die Vorzeichen der beiden Zahlen werden verglichen, bevor über die Art der auszuführenden Operation entschieden wird. Falls eine Addition verlangt wurde und die Vorzeichen gleich sind, dann wird die Addition ausgeführt; falls die Vorzeichen verschieden sind, wird eine Subtraktion ausgeführt. Falls eine Subtraktion verlangt wird und die Vorzeichen verschieden sind, dann wird eine Addition durchgeführt; falls die Vorzeichen gleich sind, wird eine Subtraktion durchgeführt. Eine spezielle Schaltung setzt das Vorzeichen für das Endergebnis in Abhängigkeit von den Vorzeichen der Argumente und vom Vorzeichen des partiellen Ergebnisses.

Addition und Subtraktion werden von einer Relaiskette gesteuert (nicht durch einen Schrittschalter), weil die Anzahl der maximal möglichen Zyklen gering ist. Abbildung 8 zeigt die Synchronisation für die Addition zweier Zahlen. Anfänglich sind die Argumente für die Addition in den Registerpaaren <Af,Bf> und <Ab,Bb> gespeichert. Im ersten Zyklus werden die Exponenten subtrahiert. Im zweiten Zyklus wird die Mantisse des größeren Exponenten in das Register Ba geladen und die Mantisse des kleineren Exponenten in das Register Bb. Die Mantisse im Register Bb wird um so viele Stellen nach rechts verschoben, wie es der absoluten Differenz der Exponenten entspricht (die Ausnahmebehandlung beschäftigt sich mit den Fällen, in denen die kleinere Zahl durch die Verschiebung 0 wird). In den Stufen I, II und III des zweiten Zyklus werden die Mantissen addiert und schließlich testet der Prozessor, ob das Ergebnis größer als 2 ist. In diesem Fall wird die Mantisse des Ergebnisses um eine Stelle nach rechts verschoben und der Exponent um 1 erniedrigt. Es ist zu beachten, daß der Test „wenn (Be>2)“ im Teil A der arithmetischen Einheit ausgeführt wird, nachdem Be bereits im Teil B während der Stufen I, II und III des zweiten Zyklus berechnet wurde.

Im Falle einer Subtraktion sind vier oder fünf Zyklen nötig. Abbildung 9 demonstriert die Synchronisation, die für eine Subtraktion gebraucht wird. Die ersten beiden Zyklen sind fast identisch mit den ersten beiden Zyklen des Additionsalgorithmus, es werden jetzt lediglich die Mantissen subtrahiert. Zyklus 3 wird nur durchgeführt, wenn die Differenz der Mantissen negativ ist. Im Endeffekt soll Zyklus 3 lediglich die Mantisse des Ergebnisses positiv machen. Zyklus 4 ist sehr wichtig: Die Differenz von zwei normalisierten Mantissen kann einige Nullen auf den höchstwertigen Bitpositionen enthalten. Das Ergebnis wird normalisiert, indem Be entsprechend viele Stellen nach links verschoben wird (dies erfolgt mit dem Shifter zwischen der Relaisschaltung F d und dem Register Bb). Die Anzahl der bitweisen Verschiebungen wird vom Exponenten im Teil A des Prozessors subtrahiert. Im Zyklus 5 wird das Ergebnis im Registerpaar <Af,Bf> gespeichert.


Zyklus Stufe Exponent Mantisse
0 I,II,IIIAe:=Aa+Ab
1 IV,V
Aa:=Ae, Ab:=Af
I,II,III
Ae:=Aa+Ab
wenn (Bf[-14]=1) dann Be:=Ba+Bb
sonst Be:=Ba
2 IV,V
Aa:=Ae, Af:=0, Ab:=0
Ba:=Be/2
I,II,III
Ae:=Aa+Ab
wenn (Bf[-13]=1) dann Be:=Ba+Bb
sonst Be:=Ba
3 IV,V
Aa:=Ae
Ba:=Be/2
I,II,III
Ae:=Aa+Ab
wenn (Bf[-12]=1) dann Be:=Ba+Bb
sonst Be:=Ba
.
.. .
.. .
.. .
..
i IV,V
Aa:=Ae
Ba:=Be/2
I,II,III
Ae:=Aa+Ab
wenn (Bf[i - 15]=1) dann Be:=Ba+Bb
sonst Be:=Ba
... ... ... ...
15 IV,V
Aa:=Ae
Ba:=Be/2
I,II,III
wenn (Be > 2) dann Ab:=1
Ae:=Aa+Ab
wenn (Bf[0]=1) dann Be:=Ba+Bb
sonst Be:=Ba
16 IV,V
Af:=Ae
wenn (Be > 2) dann Bf:=Be/2
sonst Bf:=Be
Bb:=0
Abbildung 10 Die 16 Zyklen für die Multiplikation. Das i-te Bit des Registers Bf wird mit Bf[i] bezeichnet. Der Multiplikator wird im Registerpaar <Af,Bf> gespeichert und der Multiplikand in <Ab,Bb>, bevor die Operation durchgeführt wird. Aa und Ba sind am Anfang Null.

4.4 Multiplikation

Der Multiplikationsalgorithmus der Z3 arbeitet wie eine dezimale Multiplikation mit Papier und Bleistift. Je nach dem Wert der einzelnen Ziffern des Multiplikanden führt er zur wiederholten Addition des Multiplikators oder der Null. Am Anfang des Algorithmus wird das erste Argument im Registerpaar <Af,Bf> und das zweite Argument im Registerpaar <Ab,Bb> gespeichert. Das temporäre Registerpaar <Aa,Ba> wird auf 0 gesetzt. Abbildung 10 stellt die Mikrosequenzierung durch den Schrittschalter für die Multiplikation dar. Der Algorithmus benötigt 16 Zyklen für einen Durchgang. Anzumerken ist, daß nur die Bits der Stellen -14 bis 0 des Multiplikanden benutzt werden. Die Exponenten werden im ersten Zyklus addiert und das Ergebnis läuft danach im Teil A der arithmetischen Einheit im Kreis. Die Mantissen werden im Teil B bearbeitet. Register Ba enthält das Teilergebnis der Berechnung. Die Hauptschleife der Multiplikation hat folgende Form:
      Ba:=Be/2
Be:=Ba + Bb×(i-tes Bit von Bf)
für i = -14, ..., 0. Das Teilergebnis Be wird um eine Stelle nach rechts verschoben, um Ba:=Be/2 zu produzieren. Dies erfolgt durch den Shifter, der mit der Relaisschaltung F c verbunden ist.

Das Ergebnis der Multiplikation ist eine Zahl 1 < r < 4 (für Argumente innerhalb der numerischen Grenzen). Im letzten Zyklus wird geprüft, ob r > 2. In diesem Fall wird das Ergebnis um eine Stelle nach rechts verschoben und 1 zum Exponenten des Ergebnisses addiert.

4.5 Division

Der Divisionsalgorithmus ist analog zum Multiplikationsalgorithmus, nur werden wiederholt Subtraktionen anstelle von Additionen ausgeführt. Am Anfang wird der Dividend im Registerpaar <Af,Bf> und der Divisor im Registerpaar <Ab,Bb> gespeichert. Das temporäre Registerpaar <Aa,Ba> wird auf 0 gesetzt. Abbildung 11 stellt die Mikrosequenzierung durch den Divisionsschrittschalter dar. Der Algorithmus braucht 18 Zyklen.


Zyklus Stufe Exponent Mantisse
0 I,II,III
1 IV,V
Aa:=Af
Ba:=Bf
I,II,III
Ae:=Aa-Ab
wenn (Ba-Bb > 0) dann Be:=Ba-Bb, bt:=1
sonst Be:=Ba, bt:=0
2 IV,V
Aa:=Ae
Ab:=0
Bf:=0
wenn (bt=1) dann Bf[0]:=1
Ba:=2×Be
I,II,III
Ae:=Aa+Ab
wenn (Ba-Bb > 0) dann Be:=Ba-Bb, bt:=1
sonst Be:=Ba, bt:=0
3 IV,V
Aa:=Ae
wenn (bt=1) dann Bf[-1]:=1
Ba:=2×Be
I,II,III
Ae:=Aa+Ab
wenn (Ba-Bb > 0) dann Be:=Ba-Bb, bt:=1
sonst Be:=Ba, bt:=0
... ... ... ...
i IV,V
Aa:=Ae
wenn (bt=1) dann Bf[2-i]:=1
Ba:=2×Be
I,II,III
Ae:=Aa+Ab
wenn (Ba-Bb > 0) dann Be:=Ba-Bb, bt:=1
sonst Be:=Ba, bt:=0
.
.. .
.. .
.. .
..
16 IV,V
Aa:=Ae
wenn (bt=1) dann Bf[-14]:=1
Ba:=2×Be
I,II,III
Ae:=Aa+Ab
wenn (Ba-Bb > 0) dann Be:=Ba-Bb, bt:=1
sonst Be:=Ba, bt:=0
17 IV,V
wenn (Bf[0]=0)
dann Ab:=-1
wenn (bt=1) dann Bf[-15]:=1
Bb:=0
wenn (Bf[0]=0) dann Ba:=2×Be
sonst Ba:=Be
I,II,III
Ae:=Aa+Ab
Be:=Ba-Bb
18 IV,V
Af:=Ae
Bf=Be
Abbildung 11 Die 18 Zyklen für die Division. Das i-te Bit des Registers Bf wird mit Bf[i] bezeichnet. Der Dividend wird im Registerpaar <Af,Bf> gespeichert und der Divisor in <Ab,Bb>, bevor die Operation durchgeführt wird. Aa und Ba sind am Anfang Null.

Die Grundidee des Algorithmus ist einfach. Der Exponent des Ergebnisses wird durch Subtraktion der Exponenten von Dividend und Divisor berechnet. Und nun zur Mantisse: Wir möchten x/y für die normalisierten Mantissen x und y berechnen. Da wir mit normalisierten Zahlen arbeiten, ist die erste Ziffer des Ergebnisses gleich 1, wenn x > y ist und gleich 0, wenn x < y ist. Im ersten Fall setzen wir die Ziffer des Ergebnisses auf 1 und berechnen den Rest, der x - y ist. Der Rest wird wiederum durch y geteilt. Dafür wird der Rest um eine Stelle nach links verschoben und das neue Ergebnisbit wird an der Stelle [-1] im Register Bf gespeichert (was damit den Effekt des Verschiebens wieder aufhebt). Falls das Ergebnisbit 0 ist, ist der Rest einfach x und die Division geht weiter wie im ersten Fall.

Die Hauptschleife der Division hat die folgende Form:
      Ba:=2×Be
wenn (Ba-Bb > 0) dann Be:=Ba-Bb, Bf[i]:=1
sonst Be:=Ba Bf[i]:=0
für i = 0, ..., -14. Das Teilergebnis Be wird um eine Stelle nach links verschoben, um Ba:=2×Be zu produzieren. Dies erfolgt über den Shifter, der mit der Relaisschaltung F c verbunden ist.

Das Ergebnis der Division der Mantissen ist eine Zahl 1/2 < r < 2. Diese Bedingung wird in den Zyklen 17 und 18 getestet. Falls r < 1, dann wird 1 vom Exponenten subtrahiert und das Ergebnis um eine Stelle nach links verschoben, um wiederum eine normalisierte Zahl zu erhalten.

4.6 Quadratwurzelberechnung

Der Algorithmus für die Berechnung der Quadratwurzel ist das Glanzstück der Z3. Abbildung 12 zeigt die Mikrosequenzierung des entsprechenden Befehls, der 20 Zyklen benötigt. Das Argument für die Operation wird im Registerpaar <Af,Bf> gespeichert. Das Registerpaar <Aa,Ba> wird mit 0 initialisiert. Der Algorithmus berechnet die Quadratwurzel von Zahlen mit einem geraden Exponenten. Falls der Exponent ungerade ist, dann wird die Mantisse um eine Stelle nach links verschoben und der Exponent um 1 erhöht. Der Exponent des Ergebnisses (berechnet in Zyklus 19) ist halb so groß wie der Anfangsexponent.

Die Grundidee des Algorithmus ist, die Quadratwurzelberechnung auf eine Division zu reduzieren.14 Wenn wir die Wurzel von x berechnen wollen, dann suchen wir eine Zahl derart, daß x/Q = Q ist. Das Ergebnis Q erhält man, indem man nacheinander das i-te Bit auf 1 setzt und dann prüft, ob die Bedingung x > Q2 noch gilt. Falls dies nicht der Fall ist, dann muß das i-te Bit auf 0 gesetzt werden.

Nehmen wir an, wir haben bereits Bit 0 bis Bit -i + 1 des Endergebnisses berechnet. Die Mantisse sei bezeichnet mit Q-i+1:

                  0             - 1                   - i+1
Q -i+1 = Bf [0]×  2 +  Bf[- 1]× 2   + ...+  Bf [- i + 1]2   .
Bit -i wird dann auf q-i gesetzt und es muß gelten, daß
x > Q2-i = (Q -i+1 + q- i2- i)2.
Dies ist erfüllt, wenn
x - Q2   = (x - Q2    )- 2- iq  (2Q      + 2-iq  ) > 0
      -i          -i+1       - i   -i+1       -i
Definieren wir t-i durch den Ausdruck
2-it-i = x-  Q2-i = (x - Q2-i+1) - 2-iq-i(2Q- i+1 + 2- iq-i)
Dies kann geschrieben werden als
 - i           -i+1    -i              -i
2  t-i = t-i+12    -  2  q-i(2Q - i+1 + 2  q-i)
wobei wir die rekursive Definition 2-i+1t -i+1 = (x - Q - i + 12) benutzt haben. Vereinfachen wir den letzten Ausdruck, dann erhalten wir:
                             -i
t-i = 2t-i+1-  q-i(2Q - i+1 + 2  q-i)
Für q-i = 1 erhalten wir schließlich:
t  =  2t    - (2Q      + 2-i)
 -i     -i+1      - i+1
Falls t-i > 0, dann dürfen wir Bit -i des Endergebnisses auf 1 setzen, d. h. Bf[-i]:=1. Falls t-i negativ ist, dann setzen wir Bf[-i]:=0. Die rekursive Berechnung wird mit t0 = x gestartet. Q-i+1 stellt in jedem Schritt das Teilergebnis im Register Bf dar. Be enthält in der i-ten Iteration t-i+1. Bit -i wird versuchsweise auf 1 gesetzt und das Vorzeichen von t-i wird geprüft.

Die Hauptschleife für den Algorithmus für die Quadratwurzel hat deswegen folgende Form:
      Ba:=2×Be
Bb:=2×Bf
Bb[-i]:=1
wenn (Ba-Bb > 0) dann Be:=Ba-Bb, Bf[-i]:=1
sonst Be:=Ba, Bf[-i]:=0
Alle Bits des Registers Bf werden für die Berechnung der Quadratwurzel benutzt. Falls die Ausgangszahl innerhalb der numerischen Grenzen liegt, ist auch das Ergebnis innerhalb dieser Grenzen.


Zyklus Stufe Exponent Mantisse
0 I,II,III
1 IV,V
wenn (Af[0]=1) dann Ba:=2×Bf
sonst Ba:=Bf
Bb[0]:=1
I,II,III
wenn (Ba-Bb > 0) dann Be:=Ba-Bb, bt:=1
sonst Be:=Ba, bt:=0
2 IV,V
Bf:=0
wenn (bt=1) dann Bf[0]:=1
Ba:=2×Be, Bb:=2×Bf, Bb[-1]:=1
I,II,III
wenn (Ba-Bb > 0) dann Be:=Ba-Bb, bt:=1
sonst Be:=Ba, bt:=0
3 IV,V
wenn (bt=1) dann Bf[-1]:=1
Ba:=2×Be, Bb:=2×Bf, Bb[-2]:=1
I,II,III
wenn (Ba-Bb > 0) dann Be:=Ba-Bb, bt:=1
sonst Be:=Ba, bt:=0
... ... ... ...
i IV,V
wenn (bt=1) dann Bf[2-i]:=1
Ba:=2×Be, Bb:=2×Bf, Bb[1-i]:=1
I,II,III
wenn (Ba-Bb > 0) dann Be:=Ba-Bb, bt:=1
sonst Be:=Ba, bt:=0
.
.. .
.. .
.. .
..
18 IV,V
wenn (bt=1) dann Bf[-16]:=1
Ba:=2×Be, Bb:=2×Bf
I,II,III
wenn (Ba-Bb > 0) dann Be:=Ba-Bb, bt:=1
sonst Be:=Ba, bt:=0
19 IV,V
Aa:=Af/2
Ba:=Bf, Bb:=0
I,II,III
Ae:=Aa+0
Be:=Ba+Bb
20 IV,V
Af:=Ae
Bf:=Be
Abbildung 12 Die 20 Zyklen für die Berechnung der Quadratwurzel. Das i-te Bit der Register Af und Bf wird mit Af[i] bzw. Bf[i] bezeichnet. Das Argument wird im Registerpaar <Af,Bf> gespeichert, bevor die Operation ausgeführt wird. Aa und Ba sind am Anfang Null.

5 Ein- und Ausgabebefehle

Die beiden kompliziertesten Befehle der Z3 stehen in Verbindung mit der Ein- und Ausgabe von Dezimalzahlen. Der Befehl Lu stoppt die Maschine, so daß der Operator vier Dezimalziffern und den Dezimalexponenten (zwischen -8 und 8) in die numerische Tastatur eintippen kann. Nachdem der Operator die „Automatik“-Taste gedrückt hat, übersetzt der Prozessor die Dezimalzahl in eine binäre Gleitkommazahl, die dann in das Registerpaar <Af, Bf> bzw. <Ab, Bb> geladen wird. Die Ausgabe erfolgt in die umgekehrte Richtung: Die im Registerpaar <Af, Bf> gespeicherte Gleitkommazahl wird in eine Dezimalzahl mit bis zu fünf Ziffern umgewandelt (wobei die erste Ziffer nur 0 oder 1 sein kann), und die entsprechenden Lampen werden an der Konsole zum Leuchten gebracht. Auch der Dezimalexponent und das Vorzeichen werden mit Lampen angezeigt.

5.1 Eingabe von Dezimalzahlen

Eine Dezimalzahl mit vier Ziffern, die über die Tastatur eingegeben worden ist, wird zuerst in eine binäre ganze Zahl umgewandelt. Die größte mögliche Eingabe ist die Zahl 9999, die die normalisierte Binärdarstellung 1,0011100001111×213 besitzt. Die kleinste Eingabe verschieden von Null ist 1 (0,0000000000001×213). Dies ist der Grund dafür, daß die eingegebenen Dezimalziffern ab Bit -13 des Registers Ba gespeichert werden.


Zyklus Stufe Exponent Mantisse
0 I,II,III
1 IV,V
Ba:=d4 × 2-13   Za aktiv
I,II,III
Be:=Ba+Bb
2 IV,V
Ba:=2 × Be, Bb:=8 × Be
I,II,III
Be:=Ba+Bb
3 IV,V
Ba:=d3 × 2-13   Zb aktiv
I,II,III
Be:=Ba+Bb
4 IV,V
Ba:=2 × Be, Bb:=8 × Be
I,II,III
Be:=Ba+Bb
5 IV,V
Ba:=d2 × 2-13   Zc aktiv
I,II,III
Be:=Ba+Bb
6 IV,V
Ba:=2 × Be, Bb:=8 × Be
I,II,III
Be:=Ba+Bb
7 IV,V
Ba:=d1 × 2-13   Zd aktiv
I,II,III
Be:=Ba+Bb
8 IV,V
Aa:=13
Ba:=2 × Be, Bb:=8 × Be
I,II,III
Ab:=z
Ae:=Aa-Ab
Be:=Ba+Bb
9 IV,V
Aa:=Ae
Ab:=0
Bb:=Be (normalisiert)
Abbildung 13 Die acht Zyklen, die für die Verwandlung Binär-Dezimal gebraucht werden. Das Resultat wird noch nicht gespeichert, da zuerst der Dezimalexponent gelesen werden muß. Die Zahl z bezeichnet die Anzahl der Stellen, um die die Mantisse geshiftet werden muß, um normalisiert zu werden. Aa und Ba sind am Anfang Null.

Für jede Ziffer zwischen 0 und 9 erzeugt eine Schaltung die entsprechende 4-Bit-Binärzahl (heute nennen wir dies einen BCD-Code). Die erste Ziffer kann mit der Busverbindung Za in das Register Ba übertragen werden. Die vier Bits werden in die Bits Ba[-10], Ba[-11], Ba[-12] und Ba[-13] des Registers Ba geladen. Register Bb enthält am Anfang den Wert Null. Die Zahl im Register Ba wird jetzt mit 10 multipliziert, das Ergebnis wird mit dem Inhalt von Bb addiert und die Summe wird in Bb zurückgespeichert. Die Prozedur wird wiederholt für die anderen drei Ziffern, wobei die Relais Zb, Zc und Zd die zweite, dritte bzw. vierte Ziffer in Register Ba laden. Nach vier Durchgängen ist die dezimale Eingabe in eine binäre Zahl umgewandelt worden. Die vier Durchgänge verbrauchen acht Zyklen (ein Zyklus für das Einlesen einer Dezimalziffer, ein Zyklus für die Multiplikation mit 10). Die Multiplikation mit 10 erfolgt durch einen einstelligen Shift nach links (Multiplikation mit dem Faktor 2), einen dreistelligen Shift nach links (Multiplikation mit 8) und durch Addition der beiden Werte. Abbildung 13 zeigt, wie die Dezimalzahl d4d3d2d1 im Prozessor übersetzt wird. Am Ende (Zyklus 8) wird die Mantisse normalisiert. Dies kann eine Verschiebung um z Stellen nach rechts erfordern, wobei 0 < z < 13. Die Anzahl der Stellen für den Shift muß vom Exponent abgezogen werden. Zum Exponenten wird +13 addiert, da die gelesene Zahl ab Bit -13 geladen wurde.

Nach der Bearbeitung der vier Dezimalziffern muß der Exponent berücksichtigt werden. Falls der Exponent e positiv ist, dann muß die Mantisse e mal mit 10 multipliziert werden. Falls der Exponent negativ ist, dann muß die Mantisse |e| mal mit 0,1 multipliziert werden. Die Multiplikation mit 10 ist recht einfach: die Mantisse wird mit der Binärzahl 1, 01 × 23 multipliziert. Dafür muß Be in Ba geladen werden und Be/4 in Bb (Be wird beim Kopiervorgang zwei Stellen nach rechts geshiftet). Gleichzeitig wird in Ab eine -3 geladen. Die Addition der Mantissen Ba und Bb und die Subtraktion Aa - Ab ergibt dann das gewünschte Ergebnis: das Produkt der ursprünglichen Gleitkommazahl in Ae und Be mit dem Faktor 10 (Abb. 14). Außerdem wird das Ergebnis normalisiert (in der Abb. nicht gezeigt). Für den positiven Exponenten e wird die Prozedur e mal wiederholt. Am Ende kann das Ergebnis in das Registerpaar <Af, Bf> bzw. <Ab, Bb> gespeichert werden.


Zyklus Stufe Exponent Mantisse
i IV,V
Aa:=Ae, Ab:=-3
Ba:=Be, Bb:=Be/4
I,II,III
Ae:=Aa-Ab
Be:=Ba+Bb
Abbildung 14 Multiplikation mit dem Faktor 10. Ae und Be wurden im vorherigen Zyklus berechnet. Das Resultat liegt in Ae und Be am Ende vor.

Im Fall eines negativen Exponenten wird die Multiplikation mit der Konstanten 0,1 mit Hilfe der Shifter und der Addierer geleistet. Diese Multiplikation ist etwas komplexer, weil 0,1 im Binärsystem eine periodische Zahl ist, und zwar
                  -4
0,1 (dezimal) = 2   × 1, 1001100110011001  (bin¨ar).
Zuse hat diese Multiplikation in vier Schritten implementiert. Ist die zu multiplizierende Mantisse x0, kann das Produkt mit 0,1 wie folgt berechnet werden:
1.
x1 = 1, 1 . x0 = x0 + x0/2,
2.
x2 = 1, 0001 . x1 = x1 + x1/24,
3.
x3 = 1, 00000001 . x2 = x2 + x2/28 und
4.
x4 = 1, 0000000000000001 . x3 = x3 + x3/216

Wie man sieht, ist jedesmal eine Addition und ein Shift notwendig. Am Ende des vierten Zyklus muß der Exponent -4 zum Exponenten des Resultats addiert werden.


Zyklus Stufe Exponent Mantisse
i IV,V
Ba:=Be, Bb:=Be/2
I,II,III
Be:=Ba+Bb
i + 1 IV,V
Ba:=Be, Bb:=Be/24
I,II,III
Be:=Ba+Bb
i + 2 IV,V
Ba:=Be, Bb:=Be/28
I,II,III
Be:=Ba+Bb
i + 3 IV,V
Aa:=Ae, Ab:=-4
Ba:=Be, Bb:=Be/216
I,II,III
Ae:=Aa+Ab
Be:=Ba+Bb
Abbildung 15 Steuerung der Multiplikation mit dem Faktor 0,1. Ae und Be wurden im vorherigen Zyklus berechnet. Das Resultat liegt in Ae und Be am Ende vor.

Die in den Abb. 14 und 15 dargestellten Steuerungssequenzen sind Mikroprozeduren, die nach Bedarf aufgerufen werden können. Sie werden auch für die Ausgabe von Dezimalresultaten verwendet und brauchen nicht doppelt implementiert zu werden. Die genaue Verzahnung der in Abb. 13 gezeigten Sequenz mit den beiden Prozeduren ist in der Patentanmeldung Z391 nicht weiter erläutert. Die fehlenden Details sind aber einfach zu durchschauen (Register Ab muß z. B. am Anfang der Prozeduren den Wert Null enthalten).

5.2 Ausgabe von Dezimalzahlen

Die Ausgabe arbeitet mit der wiederholten Multiplikation oder Division durch 10. Falls der binäre Exponent der Zahl im Register R1 positiv und größer als 3 ist, dann wird die Zahl so lange mit 0,1 multipliziert, bis der binäre Exponent positiv und kleiner gleich 3 ist. Ist der binäre Exponent der Zahl im Register R1 negativ, dann wird die Gleitkommazahl so lange mit 10 multipliziert, bis der Exponent positiv und kleiner gleich 3 ist. Dafür werden die oben besprochenen Steuerungssequenzen als Mikroprozeduren iterativ verwendet. Durch einen Shift der Mantisse um wenige Stellen wird dann in beiden Fällen der Exponent dem Wert 2 zugewiesen und das Resultat im Registerpaar <Ab, Bb> gespeichert.

Nach dieser Manipulation enthalten die obersten vier Bits des Resultats Be eine Zahl zwischen 00 und 15 (0000 und 1111). Diese Bits stellen die beiden obersten dezimalen Ziffern, die in den ersten beiden Spalten von den Ausgabelampen angezeigt werden sollen. Die vier Bits werden in Register Bf gerettet (an den Positionen 0 bis -3) und dann durch spezielle Kontakte in Be gelöscht.


PIC

Abbildung 16 Die vollständige Architektur der Z3

Im nächsten Schritt wird der Rest der Mantisse mit dem Faktor 10 multipliziert. Da die Mantisse nach der Löschung der obersten vier Bits kleiner als 1 ist, ist das Resultat vor dem Komma eine Zahl kleiner als 10, d. h. eine Ziffer zwischen 0 und 9. Die vier Bits vor dem Komma im Resultat Be werden jetzt an den Positionen -4 bis -7 von Bf gerettet. Danach werden diese vier Bits in Be gelöscht und der Prozeß setzt sich fort. Die dritte und vierte Ziffer ergeben sich ebenfalls durch Multiplikation mit 10 und werden an den Positionen -8 bis -11 bzw. -12 bis -15 des Registers Bf gerettet. Im Register Bf liegen die Dezimalziffern sauber voneinander getrennt vor. Sie brauchen nur zur Ausgabeeinheit übertragen zu werden, so daß die entsprechenden Lampen leuchten. Vorher jedoch wird die Dezimalzahl abgerundet. Falls der Rest der Mantisse nach dem allerletzten Schritt 0,1 ist, muß die Dezimalzahl um 1 erhöht werden. Dies wird durch eine Spezialschaltung in einem Zyklus geleistet.

Der Pseudocode für die dargestellte Operation (ohne Abrundung) ist folgender:
      Bf[0.. - 3]:= |_ Be _|
Be:=Be -  |_ Be _|
Ba:=2×Be, Bb:=8×Be
Be:=Ba+Bb
Bf[-4.. - 7]:= |_ Be _|
Be:=Be -  |_ Be _|
Ba:=2×Be, Bb:=8×Be
Be:=Ba+Bb
Bf[-8.. - 11]:= |_ Be _|
Be:=Be -  |_ Be _|
Ba:=2×Be, Bb:=8×Be
Be:=Ba+Bb
Bf[-12.. - 15]:= |_ Be _|
Be:=Be -  |_ Be _|
Nachdem die Dezimalausgabe berechnet und angezeigt wurde, stoppt die Maschine und wartet, bis der Operator die Taste „Automatik“ drückt. Die Registerpaare <Af, Bf> und <Ab, Bb> werden gelöscht, da sie nur noch Reste der Zwischenresultate der Berechnungen enthalten.

6 Die vollständige Architektur der Z3

Wir sind nun in der Lage, das Detaildiagramm der Z3 in Abb. 16 zu verstehen. Wir sehen einige Komponenten, die in den vorangehenden Abschnitten erläutert wurden.

Die Steuereinheit und die Ein- bzw. Ausgabeeinheiten wurden bereits beschrieben. Die vier Dezimalziffern der Eingabetastatur werden mit Hilfe der Relaisschaltungen Za, Zb, Zc und Zd übertragen, die eine nach der anderen aktiviert werden.

Die Relais Eg und Ei werden benutzt, um zwei nützliche Konstanten (+13 und -4) direkt in das Exponentenregister zu bringen. Der Shifter Ee zwischen den Registern Af und Aa wird für die Quadratwurzelberechnung benutzt (er teilt Af durch 2). Der Exponent des Ergebnisses (Aa) ist dann halb so groß wie der Exponent der Ausgangszahl (Af).

Ah1 ist ein Relais, das als Flip-Flop arbeitet. Wenn es auf 0 gesetzt ist, dann wird das Registerpaar <Af,Bf> für eine Leseoperation zugänglich. Wenn es auf 1 gesetzt ist, dann wird auf das Registerpaar <Ab,Bb> zugegriffen. Dieses Relais wird über die Signalleitung ai auf 0 gesetzt. Die Signalleitungen al, aj, bl und bj werden gebraucht, um bei Bedarf die Register Af, Ab, Bf und Bb zu löschen.

Der mit „Null, Unendlich“ bezeichnete Kasten unterhalb von Ae stellt die Schaltung für die Ausnahmebehandlung dar. Sie überwacht ständig den Datenbus (hinsichtlich der Ergebnisse von Operationen und des Datentransfers vom Speicher) und setzt ggf. die entsprechende Ausnahmebedingung. Der Shifter unter Be wird benutzt, um die Mantisse um eine Stelle nach rechts zu verschieben. Dies erbringt die jedesmal nötige Normalisierung der Mantisse, wenn Be>2.

F p und F q sind Relais, die Anzahl und Richtung der Verschiebungen im Shifter unter den Relaisschaltungen Fc und F a kontrollieren. F h, F i, F k, F l und F m haben die gleiche Funktion im Zusammenhang mit den anderen Shiftern. Mit diesen fünf Bits können die Zahlen zwischen -16 und 15 dargestellt werden, und dies entspricht der Anzahl und Richtung der möglichen Verschiebungen des zweiten Shifters. Jedesmal, wenn eine derartige Verschiebung ausgeführt wird, wird die Zahl, die die Relais F h bis F m darstellen, durch die Relaisschaltung Bn in das Register Ab übertragen. Dies erfolgt, um den Exponenten des Ergebnisses entsprechend zu ändern. Falls die Zahl um 10 Stellen nach links verschoben wird, dann wird +10 vom Exponenten des Ergebnisses subtrahiert. Solche großen Verschiebungen werden häufig nach Subtraktionen benötigt.

Schauen wir uns noch einmal das Diagramm für die Z3 an. Alles ergibt nun einen Sinn und sieht ebenso konventionell aus wie in jedem einfachen modernen Gleitkommaprozessor. Es ist in der Tat erstaunlich, wie Konrad Zuse in der Lage war, gleich zu Beginn eine sehr effiziente Architektur zu finden. Der Prozessor der Z3 enthält nur 600 Relais, der Speicher braucht die dreifache Menge. Zuse war gezwungen, immer wieder die logische Struktur seiner Maschine zu überdenken und zu optimieren, um soweit wie möglich Hardware zu sparen. Er hatte nicht den Luxus der fast unbegrenzten Unterstützung, die vom amerikanischem Militär für die Entwicklung des ENIAC oder von IBM für die Mark I gewährt wurde. Er war ganz auf sich allein gestellt, und obwohl dies sicher zu seinem Vorteil auf der konzeptionellen Seite wirkte, gereichte es zu seinem Nachteil, wenn man den geringen Einfluß der Z1 und der Z3 auf die aufblühende amerikanische Computerindustrie nach dem Zweiten Weltkrieg bedenkt.15

7 Die Erfindung des Computers

Das größte Manko der Z3 besteht darin, keinen Sprungbefehl zu haben. Es wäre nicht unmöglich gewesen, diesen zu implementieren: obwohl dies bei einem auf einem Lochstreifen gespeicherten Programm umständlich ist, wären nur ein paar zusätzliche Schaltkreise nötig gewesen. Manchmal wird die Trennlinie zwischen einer bloßen Rechenmaschine und einem universellen Computer mit der Unterscheidung nach intern oder extern gespeichertem Programm gezogen. Ich habe an anderer Stelle gezeigt,16 daß dies kein verbindliches Kriterium ist. Ein externes Programm kann wie ein Interpreter numerischer Daten arbeiten. Es wird fester Bestandteil des Prozessors und die Daten werden selbst zum Programm, ganz ähnlich wie eine universelle Turing-Maschine als Interpreter arbeitet. Ich habe argumentiert,17 daß universelle Maschinen einen minimalen Befehlssatz und indirekte Adressierung benötigen. Indirekte Adressierung kann durch ein sich selbst modifizierendes Programm simuliert werden, so daß der Befehlssatz das entscheidende Kriterium ist. Eine Maschine mit ausreichendem Speicher, der sowohl Daten wie Befehle faßt, und mit einem zur Ausführung der Befehle CLR (löschen), INC (inkrementieren), LOAD (lesen), STORE (speichern) und BR (springen falls Null) fähigen Prozessor ist eine universelle Maschine (dieser Befehlssatz kann weiter reduziert werden18). In diesem Sinne war die Z1 keine universelle Maschine, aber die anderen frühen Rechenmaschinen waren dies ebensowenig. Die ABC (Atanasoff) war ein Spezialrechner für die Gaußelimination, und dem Rechner Mark I aus Harvard fehlte der bedingte Sprungbefehl, obwohl er sozusagen FOR-Schleifen ausführen konnte. Der ENIAC war noch nicht einmal über Software programmierbar: die Bausteine mußten nach Datenflußart fest verbunden werden. Bedingte Sprünge waren beim ENIAC nur begrenzt verfügbar und sich selbst modifizierende Programme standen nicht zur Diskussion.



Tabelle 2 Vergleich der architektonischen Eigenschaften I
Maschine Speicher Bedingte Soft- oder Sich selbst Indirekte
und CPUSprünge? Hardware- modifizierendeAdressierung?
getrennt? programmierung Programme?
Zuses Z1  V~ × Software × ×
Atanasoff  V~ × Hardware × ×
Harvard Mark I × × Software × ×
ENIAC × teilweise Hardware × ×
Manchester Mark 1  V~  V~ Software  V~ ×
EDSAC  V~  V~ Software  V~ ×


Tabelle 3 Vergleich der architektonischen Eigenschaften II
Maschine Interne Fest- oder Bit-SequentielleArchitektur Technologie
CodierungGleitkomma? Arithmetik?
Zuses Z1 Binär Gleitkomma nein sequentiell Mechanisch
Atanasoff Binär Festkomma ja vektoriell Elektronisch
Harvard Mark I Dezimal Festkomma nein parallel Elektromech.
ENIAC Dezimal Festkomma nein Datenfluß Elektronisch
Manchester Mark 1 Binär Festkomma ja sequentiell Elektronisch
EDSAC Binär Festkomma nein sequentiell Elektronisch

Die Tabellen 2 und 3 fassen die wichtigsten Informationen für die frühen Rechner zusammen, die im Abschnitt 1 erwähnt wurden. Wie aus diesen Tabellen deutlich abzulesen ist, erfüllt keine der in den vier ersten Zeilen stehenden Maschinen alle Anforderungen für einen Universalrechner. In der Tabelle fehlt ein wichtiger Rechner: der Relay Interpolator, den George Stibitz bei den Bell Telephone Laboratories im Oktober 1939 fertigstellte. Die Maschine konnte eine Folge von arithmetischen Befehlen von einem Lochstreifen lesen und ausführen. Sie verwendete Relais, eine spezielle Zahlencodierung und Festkommaarithmetik. Sie war der Z3 funktional ähnlich und konnte wie diese keine bedingten Sprünge ausführen.

Die letzten beiden Zeilen der Tabellen zeigen die Daten für die Manchester Mark I und für EDSAC (Electronic Delay Storage Automatic Calculator), der erste „stored program computer“ der Welt. Dieser Rechner wurde an der Universität Cambridge gebaut. Die Gruppe wurde von Maurice Wilkes geleitet, der 1946 die Gelegenheit hatte, die amerikanischen Maschinen kennenzulernen. Die EDSAC war eine binäre, serielle Maschine, die mit ganzen Zahlen arbeitete. Die Programme wurden in den Speicher geladen, und neben vielen anderen Befehlen gab es auch bedingte Sprünge. Programme konnten während des Laufs modifiziert werden. Das erste Programm wurde im Mai 1949 erfolgreich ausgeführt. Die in Manchester zwischen 1946 und 1948 gebaute ‘Baby’ Mark 1 ist in den Tabellen ebenfalls aufgenommen worden, da sie (soweit es dem Autor bekannt ist) die erste Maschine war, die der Definition eines universellen Computers entspricht (d.h. ohne umständliche Programmtransformationen). Die ‘Baby’ Mark 1 wie auch die spätere Ferranti MARK I wurden unter der Leitung von F. C. Williams und T. Kilburn gebaut. Die Programme wurden in einen digitalen Speicher mit wahlfreiem Zugriff geladen, der mit Kathodenstrahlröhren implementiert wurde. Alle notwendigen primitiven Befehle waren vorhanden (in veränderter Form), und obwohl es keine indirekte Adressierung gab, konnten sich selbst modifizierende Programme geschrieben werden. Das erste Programm lief am 21. Juni 1948 und berechnete den größten Faktor von 218 mit 3.5 Millionen Operationen, wozu es 52 Minuten brauchte.19 Im September wurde Alan Turing als Dozent für Mathematik nach Manchester berufen und schrieb einige Programme für den ersten vollwertigen Computer der Welt. Seine Vision eines Universalrechners, die 1936 publiziert wurde, in demselben Jahr, in dem die Speichereinheit der Z1 fertig wurde, war mit der Mark 1 verwirklicht worden. Wie die Tabellen 2 und 3 deutlich zeigen, war die Erfindung des Computers eine kollektive Errungenschaft, die zwei Kontinente und 12 Jahre umfaßte.

8 Anhang: Bedingte Sprünge in der Z3

Wir haben in diesem Aufsatz bereits erwähnt, daß für universelle Berechnungen bedingte Sprünge notwendig sind. Der Programmfluß muß gesteuert werden können; es muß möglich sein, die letzten numerischen Resultate als Grundlage für logische Verzweigungen zu verwenden.

Die Z3 kann bedingte Sprünge simulieren. Dafür ist lediglich notwendig, den Quellcode auf eine bestimmte Art und Weise vorzubereiten. Wir zeigen in diesem Anhang, wie dies gemacht werden kann.20

8.1 Simulation des IF-Befehls

Wir zeigen zuerst, daß, falls z und i Gleitkommazahlen darstellen (ganze Zahlen), die Operation

if (z = i) then t = 0 else t = 1
in der Z3 implementiert werden kann.

Folgende Berechnung kann in der Z3 ohne weiteres durchgeführt werden:

d  =  (z - i) * (z- i)
g  =  d/(d - e)
wobei die Variable e eine in bezug auf ganze Zahlen kleine Zahl ist, z. B 0.001. Wir setzen auch voraus, daß die ganzen Zahlen z und i nicht so groß sind, daß es zum Overflow kommt. Die Variable g ist gleich Null, nur wenn z = i. Falls z/=i, ist das Resultat g etwas größer als 1. Wir möchten die Zahl „bereinigen“. Dafür wird folgende Berechnung
t = (216 + g) - 216,
in der durch die Klammerung angegebenen Reihenfolge durchgeführt. Da die Z3 intern mit 16 Bits nach dem Komma arbeitet, führt die erste Addition zu einer Verschiebung der Mantisse von g um 16 Stellen nach rechts. Alle Bits von g, außer das erste vor dem Komma, gehen bei dieser Addition verloren. Die darauffolgende Subtraktion bringt den ganzzahligen Anteil von g an seine ursprüngliche Position in der Mantisse. Damit haben wir eine ganzzahlige Variante des IF-Befehls simuliert.

8.2 Bedingte Sprünge

Nehmen wir an, daß das Programm P aus n verschiedenen Codesegmenten besteht: P 1, ..., P n. Die Variable z  (- {1, 2, ..., n} soll verwendet werden, um das Segment auszuwählen, das ausgeführt werden soll. Wir möchten also den Befehl „CASE z“ simulieren, wobei z eines der Segmente P 1, ..., P n auswählt.

Die allgemeine Strategie ist, alle n Codesegmente auszuführen, aber nur in dem Segment P z zuzulassen, daß Speicherinhalte verändert werden.

Wir transformieren das ursprüngliche Programm so, daß am Anfang eines jeden Segments i = 1, ..., n der Befehl

if (z = i) then t = 0 else t = 1
ausgeführt wird (dazu wird eine Speicherzelle für z und eine für t reserviert). Außerdem expandieren wir den ursprünglichen Code so, daß überall dort, wo ein Speichern-Befehl vorkommt, einige zusätzliche Befehle eingefügt werden. Sei z. B. der Speichern-Befehl „Ps 10“, der das Resultatregister <Af, Bf>, dessen Inhalt wir hier x nennen, in die Adresse 10 speichert. In dem transformierten Code lesen wir zuerst den Inhalt von Adresse 10, dessen Inhalt a sei, und führen folgende Berechnung aus:
a * t + (1- t) *x.
Auf Adresse 10 wird nun das Resultat gespeichert. Ist t = 0, d.h. befinden wir uns im Codesegment P z, wird in Adresse 10 der ursprüngliche Inhalt x des Resultatregisters gespeichert. Befinden wir uns nicht im Codesegment P z, so gilt t = 1 und Adresse 10 wird mit a, d. h. mit ihrem eigenen Inhalt überschrieben.

Ist diese Expansion des Codes an allen Stellen des ursprünglichen Programms durchgeführt worden, an denen sich Speichern-Befehle befinden, so ist das Ergebnis davon, daß zwar alle Codesegmente ausgeführt werden, aber nur die Ergebnisse des Codesegments P z im Speicher registriert werden. Damit ist gezeigt worden, daß die Simulation eines CASE-Befehls möglich ist.

8.3 Universalität

Mit Hilfe von IF- und CASE-Befehlen können offensichtlich sehr anspruchsvolle Programme erstellt werden. Es ist sogar möglich, eine Turing-Maschine zu simulieren.21 Wir skizzieren hier nur, wie dies gemacht werden kann.

Eine Simulation einer Turing-Maschine braucht eine WHILE-Schleife, die die Simulation abbricht, wenn der Halte-Zustand erreicht worden ist. Die Turing-Maschine wechselt ihren aktuellen Zustand Q in jeder Iteration. Die WHILE-Schleife kann simuliert werden, indem beide Enden des Lochstreifens für die Z3 zusammen geklebt werden und immer am Anfang der Schleife 0/Q berechnet wird. Wir definieren Q = 0 als den Halte-Zustand. Sollte die Turing-Maschine diesen Zustand erreichen, so stoppt die Z3, weil die undefinierte Operation 0/0 sie zum Stillstand führt. Hätte Zuse diese Ausnahmebehandlung nicht eingeführt, hätten wir keine Möglichkeit gehabt, das Programm zu stoppen.

Der Rest der Simulation der Turing-Maschine kann mit arithmetischen Mitteln und Tabellen-Lookup gemacht werden. Für den Zugriff auf Tabellen ist indirekte Adressierung notwendig. Diese kann folgendermaßen simuliert werden: Angenommen, wir möchten Speicheradresse z (1 < z < 10) lesen und in Adresse 20 speichern. Wir schreiben ein Programm mit 10 Segmenten P 1, ..., P 10. In jedem Segment wird eine feste Adresse gelesen (von 1 bis 10) und in Adresse 20 gespeichert. Wir transformieren jetzt dieses Programm so, wie im Fall der CASE-Anweisung, wobei z die Auswahlvariable ist. Obwohl alle Adressen von 1 bis 10 gelesen werden, wird nach der Transformation nur Adresse z tatsächlich in Adresse 20 gespeichert. Das Ergebnis entspricht einer simulierten indirekten Adressierung.

8.4 Fazit

Der Leser mag denken, daß diese Transformationen ziemlich umständlich sind und daß natürlich keiner auf die Idee kommen würde, die Z3 so zu programmieren. Vom theoretischen Standpunkt aus interessiert uns jedoch, alle Möglichkeiten des Programmiermodells der Z3 voll auszuschöpfen. Die Z3 könnte im Prinzip (nur im Prinzip!) eine universelle Turing-Maschine simulieren.

Das in diesem Anhang besprochene Resultat wirkt so fremd, weil die Transformationsmethode so künstlich ist. Es könnte argumentiert werden, daß die Größe der Programme unhandlich wird und daß die Berechnungen noch langsamer werden. Dies ist aber aus theoretischer Sicht unerheblich, aus praktischer Sicht natürlich maßgebend.

Das Resultat scheint unserer Intuition zu widersprechen, bis wir merken, daß Multiplikation und Division von der Z3 iterativ berechnet werden. Die Hardware trifft bei diesen Algorithmen Entscheidungen, und es gibt die notwendige Maschinerie für bedingte Sprünge. Diese Maschinerie ist jedoch in den arithmetischen Operationen eingebettet. Die hier besprochenen Transformationen bewirken, daß die Fallüberprüfungen aus der Hardware- in die Softwareebene befördert werden. Sinn und Zweck der Transformationen ist, die in der Hardware bereits vorhandenen bedingten Sprünge für den Programmierer sichtbar zu machen.

Deswegen können wir schließlich sagen, daß aus einer rein theoretischen, ganz und gar unpraktischen Perspektive, das Programmiermodell der Z3 äquivalent zum Programmiermodell von heutigen Computern ist.

Danksagung

Es war mir nur durch die Zusammenarbeit mit einigen meiner Studenten an den Universitäten in Halle und Berlin möglich, die skizzenhafte Dokumentation der Z3 zu verstehen. Ich danke Alexander Thurm und Axel Bauer, die eine Gatterebenensimulation des Prozessors der Z3 implementiert haben. Uns wurden die Synchronisationsprobleme bewußt, nachdem die Simulation nicht in Gang kommen wollte. Prof. Friedrich L. Bauer hat wertvolle Hinweise für die Überarbeitung des Manuskripts gegeben. Meine Studenten und ich fingen die Arbeit an der Z3 mit der Hilfe von Konrad Zuse an, der unsere Fragen gerne beantwortete. Es war erstaunlich zu beobachten, wie er nach fast 60 Jahren den kompletten Entwurf der Z3 noch immer im Gedächtnis hatte. Leider starb Konrad Zuse im Dezember 1995, bevor dieser Artikel über sein Werk fertig wurde. Seinem Andenken ist diese Arbeit gewidmet.