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. |
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).
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.
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.
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.
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).
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.
|
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
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 (!) |
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.
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:=![]() |
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:

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:
|
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.
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).
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 |
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.
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.
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.
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.
In diesem Abschnitt werden die numerischen Algorithmen der Z1 und Z3 offengelegt und mit Hilfe von Steuerungsdiagrammen im Detail besprochen.
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.
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
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,
-
,
/
und 0 ×
. 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
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
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.
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.
|
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.
|
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) |
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.
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.
|
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 |
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.
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 .](068725x.gif)






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

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.
|
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.
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![]() |
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
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.
|
|
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.
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
Wir zeigen zuerst, daß, falls z und i Gleitkommazahlen darstellen (ganze Zahlen), die Operation

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

i, ist das Resultat g etwas größer als 1. Wir möchten die Zahl bereinigen“.
Dafür wird folgende Berechnung

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


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