Damit sind eigentlich die wichtigsten Informationen für die Fetch-Phase verfügbar. Fassen wir sie also noch einmal zusammen:

  1. Die im Program Counter im Steuerwerk gespeicherte Adresse wird an den Decoder des Caches übermittelt (das geschieht übrigens über den sogenannten Adressbus – eine Datenleitung im Computer, die einfach mehrere getrennte Bauelemente miteinander verbindet und so auch die Datenübermittlung über größere Entfernungen ermöglicht).
  2. Der Decoder wandelt das Adresssignal derart um, dass eine einzelne Zeile im Cache aktiviert wird.
  3. Die nun am Ausgang vom Cache anliegende Bitkette wird (wieder über einen Bus, diesmal den Datenbus) zurück an das Steuerwerk übermittelt, wo sie als Instruktion im Instruktionsregister gespeichert wird.
  4. Als letztes wird noch der Program Counter aktualisiert, so dass er auf die nächste Instruktion im Speicher verweist.

Phase 2: Decode

Die größte Magie ist jetzt eigentlich schon vorbei, spannender wird es nicht mehr. In der zweiten Phase wird die nun im Instruktionsregister geladene Instruktion durch einen Decoder im Steuerwerk geschleust (wobei das Register seine gespeicherten Werte zum Beispiel einfach direkt an den Decoder ausgebe könnte), der sie in ihre relevanten Bestandteile (also den Opcode und eventuelle Adressen, Register-Identifizierer und konkrete Werte) zerlegt. Der Decoder hier arbeitet genauso wie der im Cache, nur dass diesmal eben keine einzelne Bitkette mit nur jeweils einer einzelnen 1 darin entsteht, sondern mehrere, variablere Bitketten. Nach dem Ende der zweiten Phase ist also bekannt, was gemacht werden soll und welche Daten dafür zu benutzen sind.

Phase 3: Fetch Operands

Genauso, wie in der ersten Phase die Instruktion aus dem Speicher geladen wurde, werden in der dritten Phase eventuell benötigte Daten geladen; die Adressen hierfür wurden in der vorherigen Phase ja aus der Instruktion extrahiert, sind also bekannt. Das Vorgehen ist hierbei identisch zu dem in Phase 1, lediglich mit dem Unterschied, dass die geladenen Daten in anderen Registern gespeichert werden.

Phase 4: Execute

In der letzten Phase werden schließlich alle gesammelten Daten vereint und die geladene Instruktion ausgeführt. Vereinfacht ausgedrückt ist ein Prozessor dabei so verdrahtet, dass durch den gespeicherten Opcode automatisch die passenden Steuersignale an die benötigten Teile des Prozessors gesendet werden; wenn wir an das Rechenwerk aus dem letzten Teil denken, könnte durch den Opcode also das Steuersignal für den Addier-/Subtrahiereingang generiert werden.

Zusammenfassung

Wenn man sich jetzt den ganzen Prozessor einfach um noch viel mehr (Rechen-)Funktionen angereichert vorstellt, hat man ein ziemlich gutes Bild davon, wie so ein Computer tief im Inneren funktioniert. Auch moderne Prozessoren funktionieren nach dem in diesem und den letzten Kapiteln beschriebenen Prinzip. Natürlich sind sie weitaus komplexer in der Hinsicht, dass sie mehr Register, ein viel größeres Rechenwerk und insgesamt über mehr Funktionalität verfügen, aber das Prinzip ist wirklich das gleiche.

Damit haben den technischen Teil der Arbeitsweise von Computern geklärt. Wir haben die theoretischen Grundlagen des dualen Zahlensystems geklärt; wir haben besprochen, wie aus Transistoren einfache logische Gatter aufgebaut werden können; anschließend wurde gezeigt, wie mit Hilfe dieser logischen Gatter zunächst einzelne Bits miteinander verrechnet und gespeichert werden können; danach haben wir uns mit der Speicherung von ganzen Bitketten beschäftigt und komplexere Rechenoperationen besprochen; heute schließlich wurde erklärt, wie all die vorher vorgestellten Methoden zusammenwirken und einen Prozessor formen.

Wenn im Kommentarbereich keine besonderen Wünsche über weitere technische Bestandteile eines Rechners, die hier noch besprochen werden sollen, geäußert werden, würde ich diese Reihe hiermit für (erfolgreich) beendet erklären und mich in Zukunft der Programmierung von Computern zuwenden. Wir haben schließlich zwar geklärt, wie ein Computer Instruktionen verarbeiten kann, aber woher diese Instruktionen letzten Endes kommen, ist noch offen – und hier kommt der Programmierer ins Spiel. Aber dazu in Zukunft mehr.

1 / 2 / 3

Kommentare (12)

  1. #1 etth
    August 24, 2011

    Jetzt wo bekannt ist, wie ein Prozessor Zahlen addieren kann stellt sich mir die Frage, ob die Addition denn reicht, um alle notwendigen Operationen auszuführen. Die Division ist meines Wissens die einzige Rechenoperation, die nicht als Addition umschrieben werden kann. Wie wird diese durchgeführt? Und tun die Dinger wirklich nicht mehr als so grundsätzliche Rechenoperationen durchzuführen?

  2. #2 Marcus Frenkel
    August 24, 2011

    @etth
    Die Division mit ganzen Zahlen (also Division mit Rest) lässt sich ziemlich einfach als wiederholte Subtraktion umschreiben. Von der ersten Zahl wird die zweite einfach so lange abgezogen, bis ein Wert < 0 rauskommt - dann hat man das Ergebnis und den Rest. Etwas anders sieht es natürlich bei reellen Zahlen aus - aber vor denen habe ich mich mit voller Absicht etwas gedrückt, da insbesondere die Erklärung der Rechenoperationen hier ziemlich umfangreich werden würde. 😉 Teilweise arbeiten Prozessoren mit den grundsätzlichen Rechenoperationen, teilweise sind bestimmte Operationen aber auch anders umgesetzt; da sind schon einige Tricks möglich, die dann auch meist im Rechenwerk fest verdrahtet werden. Die Multiplikation wird zum Beispiel auch nicht einfach über wiederholtes addieren umgesetzt (was ginge, aber langsam wäre), sondern über eine Kombination aus Addition und Verschiebungen (Shiften, dafür waren die Schieberegister gut). Die Rechenoperationen beschränken sich natürlich auch mehr oder weniger auf die ALU - außerhalb davon kann der Prozessor natürlich auch noch Dinge, vor allem Daten hin- und herschicken und (de-)codieren. Aber ein Großteil der Arbeit findet schon in der ALU statt - nicht umsonst wird die Leistung eines Prozessors auch in FLOPS, also floating point operations per second (im Grunde Berechnungen) angegeben.

  3. #3 Dagger
    August 25, 2011

    Schöne Serie! Erinnert mich gut ans Studium 🙂

  4. #4 Jan von nebenan
    August 26, 2011

    Sehr schöner Artikel! Ein paar technische Sachen gäbe es vielleicht schon noch, aber ich weiß nicht, ob das nicht zu tief in die Materie geht. Ich fände z.B. interessant, mal auf die Features der neueren Prozessoren einzugehen. Die sich ja nicht nur deswegen so schnell, weil die Taktfrequenz höher ist: SIMD, Pipelining etc. wären solchen Themen, oder auch “intelligente” Funktionen wie branch prediction (Prozessor versucht zu ermitteln, ob eine If-Bedigung wahr oder falsch sein wird, und lädt entsprechende Daten vor – Trefferquote bis 98% bei modernen CPUs).

    Und eine Sache noch: Misst man die Leistung der ALU nicht in MIPS (million instructions per second)? FLOPS bezieht sich doch auf die FPU, die du ja geschickt ausgelassen hast… 😉

  5. #5 Marcus Frenkel
    August 26, 2011

    @Jan von nebenan
    Ui. Branch prediction ist natürlich ein ganz schöner Brocken. 😉
    Pipelining wäre aber in der Tat ganz interessant; ich hatte überlegt, es noch in diesem Artikel zu bringen, es dann aber auf Grund der Länge gelassen. SIMD ginge ja Richtung Prozessorarchitektur – da müssen dann auch noch SISD, MISD und MIMD erklärt werden. Ich überleg mir mal, ob das schon zu technisch ist oder nicht…oder zu magisch, da ich da auch nicht alles erklären kann und oft genug auf die Verdrahtung in der CPU verweisen muss. 😉

    Das mit den FLOPS war etwas ungeschickt ausgedrückt, ja. Man misst die Leistung einer ALU unter anderem in FLOPS (und meint dann damit die FPU darin). Die MIPS gibt es ja auch, aber die sind ähnlich aussagekräftig wie die Taktrate. 😉

    Und mit der FPU werde ich mich nur beschäftigen, wenn hier mindestens 5 Leute einen derartigen Wunsch äußern – Gleitkommawerte sind einfach zu garstig und mathematisch. 😉

  6. #6 icehawk
    August 27, 2011

    Erstmal möchte ich sagen, dass ich den Wunsch von Jan teile und auch gerne etwas über moderne Features lesen würde.

    Aber zu deiner einen Anmerkung:
    “für die technisch Versierteren: damit das funktioniert, muss die an BL/BL angelegte Spannung größer sein als die in den Transistoren gespeicherte, um den aktuellen Wert zu überschreiben”
    Das verwirrt mich etwas: Braucht man dann nicht mit der Zeit immer höhere Spannungen? Bei mehreren Ghz kommen ja schon ein paar Überschreibvorgänge zusammen: Wann geht der CPU der Saft aus? ^^

  7. #7 Marcus Frenkel
    August 27, 2011

    @icehawk
    Das Wort “gespeichert” war hier etwas unglücklich gewählt – ein Transistor speichert natürlich keine Spannung, das wäre ein wenig schwierig. Aber die beiden Transistor-Paare in der Mitte “speichern” ein Bit dadurch, dass sie sich in einem von zwei sogenannten stabilen Zuständen befinden, was die Verteilung der Leitfähigkeit und damit Spannung angeht – es reicht übrigens eine sehr niedrige Spannung, um so einen Zustand aufrecht zu erhalten. Zum Überschreiben muss kurzfristig eine stärkere Spannung angelegt werden, um die bisherige zu “überschreiben” – aber die stärkere Spannung bleibt nicht in den Transistoren bestehen. Somit braucht man auch nicht immer höhere Spannungen.

  8. #8 Engywuck
    August 31, 2011

    och, gegen FPU in leicht verdaulicher Form hätte ich nichts einzuwenden 😉 Addieren kann ja jeder ^^

    Zum Thema “Multiplizieren über Addition”: mein Opa hatte einen mechanischen Tischrechner (mit Motor) mit den drei Grundrechenarten: Addition, Subtraktion, Multiplikation (Division ist ja nicht einfach….). Damit habe ich als Kind gerne gespielt 🙂
    Man überlegt sich dann aber recht schnell, ob man “4 * 50” oder “50 * 4” berechnet. In ersterem Fall wird 4 – plus 4 – plus 4 – plus 4 …. gerechnet. Das Ganze mit Höllenlärm wegen der Mechanik samt Motor und entsprechendem Zeitaufwand (so 1-2 Operationen pro Sekunde….).
    Angeschafft wurde das Teil damals übrigens von der Milchgenossenschaft im Ort, weil mein Opa als “Zahlstelle” sich geweigert hat, die Auszahlungen von Hand zu berechnen. Bei seinem Vorgänger hatten die Mitglieder sich immer beschwert, er habe falsch gerechnet, mit der Maschine haben sie’s dann einfach geglaubt… 😉

  9. #9 Marcus Frenkel
    August 31, 2011

    Ja ja, die lieben Optimierungen bei der Befehlsausführung. Die gibt es ja immer noch – nur in hochkomplexer Form. 😉

    Ok, da sich nun einige was zu Gleitkommazahlen gewünscht haben, werde ich dazu wohl auch noch irgendwann einen Artikel bringen, in der Hoffnung, damit nicht die letzten Leser zu vergraulen. 😉

  10. #10 rolak
    September 4, 2011

    Hi etth, mit einer den üblichen Divisions-Algorithmen angemessenen Verzögerung: Da Fließkommazahlen letztendlich nur ganze Zahlen sind, läßt sich auch deren Division auf add/sub reduzieren. Es gibt meines Wissens nur einen wesentlichen Unterschied: Liegt ein HW-Multiplizierer für n-bit-Zahlen vor, kann mit minimalem Aufwand ein Algorithmus für k*n-bit-Zahlen implementiert werden (k² zu addierende Zwischenergebnisse) während einem ein HW-Dividierer diese Möglichkeit nicht bietet.
    In der Praxis werden jedoch schnellere Techniken genutzt (SRT, N/R, Goldschmidt) — was dann vielleicht schon erste Vorschläge für den FPU-Artikel wären, da ansonsten doch exakt genauso gerechnet wird wie vom schriftlichen multiplizieren/dividieren gewohnt. Nur halt im Binärsystem.

    Branch predicition ist doch, wenn auch wesentlich für Tempo und effiziente Pipeline-Auslastung, ‘nur’ eine Kombination aus statistischer Auswertung (zB saturating counter) und Schmierzettel (zB BTB).
    Beim Z80 war die Ausführungszeit ja noch fest – doch auch in diesem Zusammenhang hatte ich ziemliche Schwierigkeiten, einen Programmierer davon zu überzeugen, daß ~150 gesparte Takte bei dem 1aus256-Sonderfall die je 2 Takte für den nicht ausgeführten bedingten Sprung in keiner Weise aufwiegen. Auch eine Art von branch prediction 😉

    Du wirst schon keinen vergraulen, Marcus. Schlimmstenfalls werden einige posts seltener gelesen als andere(wenn schon nicht seltener geklickt), doch das dürfte bei noch so sorgfältiger Vorabfilterung eigentlich bei keinem Themenkomplex zu vermeiden sein.

  11. #11 Michi
    September 23, 2011

    Vielen vielen Dank! Die Serie hat mir viel geholfen!

  12. #12 ilikepepsi
    September 26, 2011

    @Marcus:

    Hi, hast du vor in der “Programmierung von Computern” Reihe die Funktionsweise von Compilern näher zu beleuchten? Falls nicht, das fände ich sehr interessant.