Prozessorgrundlagen: Von-Neumann-Architektur, Teil 2

26.05.2004 von PROF. DR. CHRISTIAN SIEMERS 
Seit fast 60 Jahren basieren alle wichtigen Prozessorarchitekturen auf dem Von-Neumann-Rechnermodell. Wer sich auch nur ansatzweise mit Mikroprozessoren beschäftigt, kommt ohne dieses grundlegende Wissen nicht aus.

Die Konzeption des Von-Neumann-Rechners zeigt innerhalb der Central Processing Unit (CPU) eine Zweiteilung der Aufgaben in Control Unit (Leit- oder Steuerwerk) und Arithmetical Logical Unit (Rechenwerk).

Das Leitwerk hat dabei im Wesentlichen die Aufgabe, den gesamten Programmablauf sowie den der einzelnen Instruktionen jeweils in ihrer zeitlichen Sequenz zu steuern. Die arithmetischen und logischen Rechenkapazitäten sind hingegen im Rechenwerk zusammengefasst.

Serie: Prozessorgrundlagen: Von-Neumann-Architektur

Teil 1

Bussysteme und Speicherarten

Teil 2

Leit-/Rechenwerk und Registermodell

Teil 3

Befehlssatz, Adressierungsarten und Interrupt-Konzept

Diesen Artikel und eine ganze Reihe weiterer Grundlagenthemen zu Prozessoren finden Sie auch in unserem tecCHANNEL-Compact "Prozessor-Technologie". Die Ausgabe können Sie in unserem Online-Shop für 9,90 Euro versandkostenfrei bestellen. Ausführliche Infos zum Inhalt des tecCHANNEL-Compact "Prozessor-Technologie" finden Sie hier.

Register im Leit- und Rechenwerk

Beide Teileinheiten benötigen zur Befehlsbearbeitung Speicherplatz, der ausschließlich vom Prozessor verwaltet wird und außerhalb des "normalen" Code- beziehungsweise Datenspeichers liegt. Diese Speicherstellen bezeichnet man im Allgemeinen als Register. Sie sind in drei Kategorien eingeteilt:

Die für eine maschinennahe Programmierung direkt ansprechbaren Register sind im Registermodell (dazu später) zusammengefasst. In diesem Fall müssen die Register auch adressiert werden beziehungsweise dienen im Fall der Nutzung als Adressregister zur Adressierung von Speicherzellen.

Die Register in einem Prozessor lassen sich hierbei nicht immer eindeutig einem Bereich (Leitwerk oder Rechenwerk) zuordnen. Am ehesten gelingt dieses für die Datenregister, die im Bereich des Rechenwerks (ALU) liegen. Diese Register besitzen eine zentrale Rolle im Rahmen der Berechnung neuer Werte. In modernen Konzepten wird die Anzahl der Datenregister möglichst auf hohem Niveau gehalten, da die Ausführungszeiten von Befehlen mit internen Daten deutlich unter denjenigen mit Daten aus dem Speicher liegen.

Die erwähnten Adressregister können dem Leitwerk (CU) zugerechnet werden. Diese Register sind für eine Adressierung von Operanden zuständig, die nicht in der sequenziellen Abfolge des Programmzählers liegen. Diese Adressregister werden im Rahmen der Befehlsbearbeitung mit der berechneten Adresse geladen und bestimmen während des Bustransfers die am Adressbus liegenden Signale. Zu den Steuerregistern, die wiederum weitest gehend dem Leitwerk zuzuordnen sind, zählen der Programmzähler, das Statusregister und der Stackpointer des Prozessors. Den Stackpointer kann man auch als Adressregister mit zusätzlicher Funktionalität bezeichnen.

Aufgaben des Leitwerks

Das Leit- oder Steuerwerk des Von-Neumann-Prozessors ist sowohl in älteren als auch aktuell in einfacheren Architekturen als zentraler Automat ausgeführt. Hierin werden folgende Aufgaben erfüllt:

Beide Aufgaben ergeben die Ablaufsteuerung eines Programms.

Diese Aufgaben lassen sich sehr gut zentralisieren, sofern die Kommunikationslängen im Prozessor eine untergeordnete Rolle spielen. Ein Vorteil der zentralen Lösung ist auch, dass jederzeit Rückmeldungen aus den einzelnen Teilen berücksichtigt werden können. Das Grundmodell des Von-Neumann-Rechners geht davon aus, dass alle Teilaktionen für einen Befehl ausgeführt sind, bevor der nächste beginnt.

Mit Einführung des Phasen-Pipelinings ergibt sich eine verteilte Ausführung der Befehle und so auch eine verteilte Struktur des Leitwerks. Dies ist bei modernen Architekturen auch deshalb notwendig, weil die Signalübermittlung im Prozessor bei großen Entfernungen einen wesentlichen Teil der Verzögerung ausmacht.

Rechenwerk

Das Rechenwerk (Arithmetical Logical Unit, ALU) in einem Von-Neumann-Prozessor ist im eigentlichen Sinn kein Rechenwerk, sondern ein Rechennetz, wenn man es mit den Begriffen Schaltwerk und Schaltnetz [4] vergleicht. Es beinhaltet mehrere Komponenten zur Durchführung aller benötigten Berechnungen. Hierzu zählen mindestens das oder die Datenregister, das eigentliche Berechnungsschaltnetz (die ALU) und die verbindenden (internen) Datenbusse.

Oft kommen weitere Komponenten zum Rechenwerk hinzu. So sind beispielsweise Adressrechnungen für berechnete Sprungadressen durchzuführen. Dies lässt sich innerhalb der zentralen ALU, jedoch auch im Rahmen eigenständiger Einheiten, integrieren. Wir beschränken uns auf die minimalen Komponenten im Rechenwerk. Weiter führende Darstellungen sind etwa in [5] zu finden.

Das Rechenwerk im engeren Sinn integriert alle Berechnungskapazitäten für neue Datenwerte innerhalb des Prozessors. Bei speziellen Einheiten wie Multiplizierern, Multiply-Accumulate-Einheiten (MAC) oder Barrel-Shiftern gibt es Ausnahmen von dieser Regel, diese sind häufig separat angeordnet.

Die ALU besteht aus einem von außen steuerbaren Schaltnetz mit zwei Datenbussen am Eingang und zwei am Ausgang. Das Bild "ALU" gibt einen Überblick. Die Steuereingänge werden von dem Leitwerk mit Signalen belegt, die aus dem Befehlswort extrahiert sind. Sie konfigurieren das Schaltnetz für den Zeitraum der Berechnung auf die gewünschte Verknüpfung. Die Operation zwischen den Daten ist dabei in Zusammenhang mit der Interpretation der jeweiligen Darstellung zu sehen. Folgende Klassen von Verknüpfungen sind in der ALU integriert:

Registermodell

Das Registermodell gehört zu den "sichtbaren" Teilen des Prozessors: Die Software-Entwicklung auf maschinennaher Ebene kann und muss die durch Maschinenbefehle in ihren Werten veränderlichen Register berücksichtigen. Die Variabilität bezieht sich dabei sowohl auf Register, die in Verbindung mit der ALU stehen (Datenregister), als auch auf Register, die zum Leitwerk gehören (Kontrollregister).

Das Bild "Mindestsatz" zeigt ein minimales Registermodell, wie es zum Beispiel in "kleinen" 8-Bit-Mikro-Controllern zu finden ist. Hierbei wird deutlich, dass die daten-bezogenen Register (Statusregister, Akkumulator) in der typischen Datenbreite ausgeführt sind. Die adressbezogenen Register (Stackpointer, Programmzähler) wurden mit der hier angenommenen Breite von 16 Bit für die Adressen gewählt.

Programmzähler

Das zentrale Register im Leitwerk ist der Programmzähler (Program Counter, PC, auch Instruction Pointer, IP). Dieses Register zeigt auf die aktuelle Stelle im Programmspeicher, die sich in Bearbeitung befindet.

Der Programmzähler des Prozessorsc wird regelmäßig dem Programmfluss entsprechend modifiziert:

Der Programmzähler kann auf Grund der vorgenannten drei wesentlichen Eigenschaften als ladbarer Binärzähler aufgefasst werden, gegebenenfalls mit Reset- beziehungsweise Set-Funktion seiner internen Flipflops.

Statusregister

Das Statusregister eines Prozessors ist ein wichtiges Interface zwischen Leit- und Rechenwerk. Hier sind üblicherweise einige Statusbits, so genannte Flags, gespeichert. Deren Werte stammen aus den Berechnungen des Rechenwerks, speziellen Befehlswörtern des Kontrollflusses oder Betriebszuständen des Prozessors.

Einige Flags eines typischen Statusregisters sind im Bild "Statusregister" dargestellt. In dieser oder ähnlicher Form sind sie häufig in Prozessoren integriert:

Neben den hier genannten Beispielen existieren in den verschiedenen Prozessorarchitekturen weitere Flags, insbesondere zur Erweiterung der arithmetischen Kapazitäten und zur Einführung bedingter Befehle (so genannte Predicate Flags).

Stackpointer

Ein Stack (Stapelspeicher, Kellerspeicher) ist ein wichtiges Hilfsmittel zur Realisierung von Unterprogrammen und Unterbrechungen. Dieser Speicherbereich ist - im Gegensatz zum allgemeinen Speicher - nicht mit einem wahlfreien Zugriffsverfahren zu erreichen, das Zugriffe in beliebiger Adressfolge ermöglicht. Der nächstfolgende Transfer vom oder zum Stack ist von der Adresse des vorhergehenden abhängig.

Es existieren aktuell zwei Varianten der Stack-Realisierung. Die schnellere Variante benutzt einen ausgezeichneten Speicherbereich, der direkt im Prozessor implementiert ist und durch keinen anderen Zugriff zu erreichen ist. Diese Form des Stacks fällt meist recht klein aus, da Siliziumfläche auf dem Prozessor-Die benötigt wird. Andererseits ist der Zugriff sehr schnell, auch für Mehrfachzugriffe, da das (langsame) externe Bussystem umgangen wird.

Die zweite Variante benötigt einen Stackpointer im Prozessor und bildet jeden Stack-Zugriff auf den (externen) Speicher ab. Diese Variante ist die meist genutzte, da sie Ressourcen schonend ist. Nachteilig sind die Geschwindigkeit sowie die immanenten Fehlermöglichkeiten, da der Speicherbereich des Stacks auch durch andere, "normale" Datenzugriffe erreichbar ist.

Der Stack arbeitet in beiden Varianten nach dem LIFO-Prinzip (Last In First Out), das sich mit einem Tellerstapel vergleichen lässt: Lese- und Schreibzugriffe beziehen sich hierbei immer auf den obersten Teil des Stapels (Top of Stack). Schreibzugriffe zielen auf das nächste freie Element, Lesezugriffe auf das oberste besetzte Element, das damit gleichzeitig für neue Schreibzugriffe freigegeben wird.

Drei Aktionen nutzen den Stack während der Bearbeitung eines Programms:

Beispiel zum Stackpointer

Für einen explizit formulierten Datentransfer zwischen einem Datenregister (das hier mit Akkumulator bezeichnet ist) und dem Stack gibt es bei vielen Prozessoren zumeist die besonderen Transferbefehle PUSH und POP:

PUSH A A (r) (--SP)
POP A (SP++) (r) A

PUSH A schreibt den Inhalt des Akkumulators in die Speicherzelle, auf die der Stackpointer SP zeigt, nachdem er zuvor dekrementiert wurde (Predekrement). POP A kopiert hingegen zunächst den Inhalt der Speicherzelle, auf die SP zeigt, in den Akkumulator und erhöht anschließend SP um 1 (Postinkrement, Bild "Stack-Operation"). In diesem Beispiel "wächst" der Stack nach unten (zu kleineren Adressen hin), wenn Daten abgelegt werden.

Die Adressierung der Speicherzelle erfolgt damit relativ zum Stackpointer. Dieses Register muss bei Start des Rechners nach Reset entweder durch die Hardware oder durch einen kurzen Abschnitt in der Software auf einen definierten Anfangswert gesetzt werden, um einen definierten Zustand zu erhalten und gegebenenfalls sporadisch auftretende Programmfehler zu verhindern. Zudem kann es durch einen zu kleinen Stack zu Abstürzen kommen, indem mehr Speicherplatz genutzt werden soll, als real vorhanden ist. Dies resultiert je nach Architektur in einem "Wrap Around". Der Stackpointer fängt wieder am Anfang an (also zum Beispiel bei hohen Adressen). Man spricht dann von Stack Overflow.

Datenregister

Grundsätzlich unterscheidet man zwei verschiedene Implementierungen von Datenregistern innerhalb des Rechenwerks. In einer Stack-orientierten (Rechenwerk-)Architektur sind die Register ähnlich wie im allgemeinen Stack in einer LIFO-Struktur angeordnet. Auch für die internen Register existiert hier ein Stackpointer, der auf das aktuelle Register zeigt. Diese Architektur, die die umgekehrte polnische Notation (Reverse Polnish Notation, RPN) für die Formulierung von Algorithmen benötigt, wird derzeit kaum noch verwendet, da die Unterstützung durch Hochsprachen (zum Beispiel Forth) sehr gering ist.

Die andere Implementierung organisiert die Datenregister in einem Registerblock, bei einer größeren Anzahl auch Registerfile genannt, mit einer wahlfreien Adressierung innerhalb des Rechenwerks. Die Wahlfreiheit des Zugriffs bedeutet, dass die Befehlswörter aus dem Programmspeicher, die eine Aktion im Rechenwerk beinhalten, in beliebiger Reihenfolge stehen dürfen (abgesehen von den Abhängigkeiten des Datenflusses).

Das Befehlsformat eines Prozessors kann 1-, 2- und 3-Adressbefehle beinhalten, in Ausnahmefällen auch mehr. Mit den Adressen sind die Quellen und das Ziel der Operation bezeichnet, so dass beispielsweise bei einer üblichen Addition zwei Quellen mit einem Ziel über die additive Verknüpfung verbunden sind. Die Varia-bilität in der Anzahl der Adressen begründet letztendlich die konkrete Ausführung der internen Daten- und Adressierungsbusse.

Klassifizierung von Prozessoren gemäß Operandenzugriff

Die Form des Operandenzugriffs für eine Operation ist sehr charakteristisch für Prozessorklassen, da sie das interne Speichermodell bestimmt. Aus diesem Grund wird diese Klassifizierung häufig genutzt.

Dieses interne Speichermodell trifft Aussagen darüber, wie die für Datenopera-tionen, etwa eine Addition, notwendigen Operanden vor und nach der Ausführung im Zugriffsbereich des Prozessors liegen. Hierbei unterscheidet man drei grundsätzliche Methoden:

Vor- und Nachteile der Prozessorklassen

Die genannten Prozessorklassen haben Vor- und Nachteile, die in der folgenden Tabelle zusammengefasst sind. Es bestehen daneben noch einige weitere Möglichkeiten zur Klassifizierung der Prozessoren. Ein Beispiel hierfür ist die Unterscheidung, ob der Zieloperand explizit angegeben werden kann oder implizit mit einem der Quelloperanden übereinstimmt.

Vor- und Nachteile der Prozessorklassen

Typ

Vorteile

Nachteile

Stack

Keine explizite Angabe von Operanden notwendig, daher minimale Opcodelänge für Arithmetikbefehle

Umfangreiche Austauschoperationen von und zum Stack notwendig, das heißt gegebenenfalls wachsende Codegröße

Akkumulator

Teilweise implizite Operandenangabe möglich (1. Quelloperand, Zieloperand). Einfachste Architektur, Verzicht auf Stack möglich

Das zentrale Register wird sehr stark genutzt, daher gegebenenfalls Engpass mit Notwendigkeit zur Zwischenspeicherung

Register-Speicher

Daten können ohne Ladezugriff für Operationen genutzt werden

Ladezugriffe im Speicherbereich benötigen wesentlich mehr Zeit, daher gegebenenfalls Verzögerung gegenüber Registerzugriff

Register-Register

Schnellstmögliche Operationen durch Registeroperanden

Explizite Ladezugriffe notwendig, Codegröße wächst

Ausblick

Eine genaue Betrachtung der Phasen der Befehlsbearbeitung und - als Erweiterung des Von-Neumann-Rechners - das Interrupt-Request-Konzept - bilden den Abschluss dieser Artikelserie im dritten Teil. (mec)

Serie: Prozessorgrundlagen: Von-Neumann-Architektur

Teil 1

Bussysteme und Speicherarten

Teil 2

Leit-/Rechenwerk und Registermodell

Teil 3

Befehlssatz, Adressierungsarten und Interrupt-Konzept

Diesen Artikel und eine ganze Reihe weiterer Grundlagenthemen zu Prozessoren finden Sie auch in unserem tecCHANNEL-Compact "Prozessor-Technologie". Die Ausgabe können Sie in unserem Online-Shop für 9,90 Euro versandkostenfrei bestellen. Ausführliche Infos zum Inhalt des tecCHANNEL-Compact "Prozessor-Technologie" finden Sie hier.

Literatur

[1] Christian Siemers: Prozessorbau - München, Wien: Carl Hanser Verlag, 1999

[2] Oberschelp, W.; Vossen, G.: Rechneraufbau und Rechnerstrukturen - 8. Auflage - München, Wien: R. Oldenbourg-Verlag, 2000

[3] Schiffmann, W.; Schmitz, R. ; Weiland, J.: Technische Informatik 2, Grundlagen der Computertechnik - 2. Auflage - Berlin, Heidelberg, New York: Springer Verlag, 2001

[4] Christian Siemers, Axel Sikora (Hrsg.): "Taschenbuch Digitaltechnik", Fachbuchverlag Leipzig im Carl Hanser Verlag, München, Wien, Januar 2003. ISBN 3-446-21862-9

[5] Oberschelp, W.; Vossen, G.: Rechneraufbau und Rechnerstrukturen- 8. Auflage - München, Wien: R. Oldenbourg-Verlag, 2000