Das sind sehr viele komplexe Fragen. Hoffentlich liest du das alles, was ich jetzt schreibe. Eigentlich wird das meiste davon sogar schon an Gymnasien im Informatik-Unterricht gelehrt und entspricht einem ganzen Semester...
Logikgatter
Ich weiß dass eine CPU aus unzählig vielen Transistoren besteht. Somit ein Binärsystem besitzt (1;0).
Allein mit dem Prinzip der Transistoren kommt man nicht weiter, das ist zu nah an der wirklichen Hardware. Um etwas Komplexes wie einen Computer zu entwickeln, ist stets Abstraktion erforderlich. Die erste Abstraktionsebene stellen dabei die sogenannten Logikgatter dar. Diese basieren auf dem EVA-Prinzip: Binäre Eingaben werden durch eine Schaltung (bestehend aus Transistoren) in binäre Ausgaben umgewandelt. Dabei existieren drei Grundgatter:
Es gibt AND-, OR- und NOT-Gatter. Hier findest du zugehörige Symbole und Tabellen detailliert erklärt.
Das UND-Gatter liefert am Ausgang nur eine 1, sofern beide Eingaben 1 sind. Das ODER-Gatter liefert am Ausgang eine 1, sofern mindestens eine der beiden Eingaben 1 ist. Das NICHT-Gatter liefert am Ausgang eine 1, sofern die Eingabe 0 ist, ansonsten liefert es eine 0. Diese Gatter basieren auf bestimmten elektrischen Schaltungen, welche aber im weiteren Verlauf nicht mehr relevant sind. Es ist wichtig, dass man das Prinzip der Gatter verinnerlicht hat, bevor man sich Gedanken über eine CPU machen kann.
In der Praxis werden zwar die drei Grundgatter oft alle durch NAND-Gatter umgesetzt, aber das vernachlässigen wir der Einfachheit halber mal.
Zum Ausprobieren eignet sich das Programm LogicSIM.
JKMS-Flip-Flop
Die Grundgatter lassen sich zu komplexeren Schaltungen zusammenschließen, sodass wir beispielsweise sogar Daten speichern können. Wichtig sind noch die sogenannten JK-Flip-Flops sowie Multiplexer. Ein JKMS-Flip-Flop sieht so aus:
Der mittlere Eingang dient für ein Taktsignal, d. h. eine regelmäßige Abfolge von Einsen und Nullen:
Bei einer steigenden Taktflanke werden die Eingaben eingelesen, bei der nächsten fallenden Taktflanke ausgegeben. Sofern der obere Eingang beim Einlesen gesetzt ist, wird eine 1 gespeichert. Ist dagegen der untere Eingang beim Einlesen gesetzt, wird eine 0 gespeichert. Der gespeicherte Wert liegt am Ausgang an. Der untere Ausgang ist dasselbe, nur negiert. Ein JKMS-Flip-Flop ist eigentlich eine Zusammensetzung aus zwei JK-Flip-Flops. Ein JK-Flip-Flop wiederum ist aus einem RS-Flip-Flop zusammengesetzt. Dieses sieht mit den Grundgattern so aus, damit du dir vorstellen kannst, wie das überhaupt funktionieren kann:
Geschickt, oder? Jedenfalls werde ich jetzt nicht erklären, wie man davon zum JK-Flip-Flop und letztendlich zum JSMS-Flip-Flop kommt. Das ist auch gar nicht so relevant. Baue das mal in LogicSIM nach und spiele ein bisschen herum, schaue dir an, wie das reagiert.
Multiplexer
Ein Multiplexer wählt aus einer Reihe von Eingaben eine aus und schaltet diese an den Ausgang durch. Hier die Schaltung für einen 1-MUX:
s ist quasi ein Schalter. Ist s 0, so wird der obere Ausgang durchgeschaltet, ansonsten der untere. Ebenso gibt es auch einen 2-MUX, welcher zwei Schalteingänge besitzt und somit vier verschiedene Eingaben durchschalten kann.
Das reicht erst einmal an Grundlagen. Das waren nur mal ein paar Beispiele. Die weiteren Grundlagen musst du für ein tieferes Verständnis recherchieren und dir erarbeiten.
Von-Neumann-Architektur
Die Von-Neumann-Architektur bildet die Grundlage für den Aufbau heutiger Computer:
Quelle: Lukas Grossar, Von-Neumann Architektur, CC0, Wikimedia Commons
Die CPU ist dabei aus Rechenwerk (ALU) und Steuerwerk zusammengesetzt. Über ein Bus-System können diese mit dem Ein-/Ausgabewerk sowie dem Speicherwerk kommunizieren. Nur in diesem Verbund ergeben die einzelnen Komponenten überhaupt Sinn. Wenn du die Funktionsweise einer CPU klären möchtest, musst du immer alle weiteren Komponenten in die Überlegungen hinzuziehen.
Ein Modellrechner
Der Aufbau heutiger Prozessoren ist sehr komplex. Daher ist es fast unmöglich, anhand der Struktur einen Einblick in Aufbau und Funktionsweise eines Computers zu bekommen. Aus diesem Grund wird oftmals ein Modellrechner zur Rate gezogen, dessen Struktur vereinfacht ist. Der grobe Aufbau des im Folgenden betrachteten Modellrechners ist in der folgenden Abbildung dargestellt:
Wie aus der Abbildung hervorgeht, ist ein Computer modular aufgebaut. Deshalb ist es sinnvoll, die Funktion jeder Komponente im Einzelnen zu beschreiben:
- Der Taktgeber: Aus einem Dauertaktsignal werden fünf Taktimpulse generiert: Die ersten vier Takte dienen der Rechnung, der fünfte Takt dient der Erhöhung des Befehlszählers um eins und dem Übertragen des aktuellen Befehls aus dem RAM in das Befehlsregister.
- Der Befehlszähler: Legt fest, welcher Befehl aus dem RAM ausgelesen wird, indem er die jeweilige Speicherzelle adressiert.
- Der RAM: Hier werden alle Befehle gespeichert.
- Das Befehlsregister: Das Befehlsregister erhält aus dem RAM mithilfe der Adressierung durch den Befehlszähler den aktuell durchzuführenden Befehl und speichert diesen.
- Das Steuerwerk: Das Steuerwerk gibt je nach Belegung des Befehlsregisters unterschiedliche Signale an die Bauteile ab.
- Das Eingaberegister: Das Eingaberegister speichert eine Zahl, welche beim nächsten Taktsignal an das Rechenwerk übergeben wird.
- Das Rechenwerk (ALU): Hier wird die Zahl aus dem Eingaberegister mit der Zahl aus dem Akkumulator verrechnet. Das Ergebnis wird wiederum im Akkumulator gespeichert, sodass damit weiter gerechnet werden kann.
- Ausgaberegister: Bei einem bestimmten Befehlscode wird der Wert des Akkumulators in das Ausgaberegister geschoben und dort als Ausgabe zwischengespeichert.
Eine solche Schaltung kann konkret folgendermaßen realisiert werden:
Programmierung des Modellrechners
Damit kannst du beispielsweise 2+2 rechnen. Der obige Rechner ist wenig flexibel – du musst alles von Hand machen. Daher verlinke ich einfach mal eine 4-Bit-CPU:
https://simulator.io/board/AWZpw7Fy3I/2
Das ist letztendlich die praktische Umsetzung obiger Überlegungen. Der Befehlssatz der CPU ist dort ebenfalls aufgeführt:
https://imgur.com/a/zuRd1ZP
Nehmen wir als Beispiel mal kein Videospiel sondern eine Matheaufgabe: Wenn ich 2+2 rechnen will, wird dann einfach ein Code aus mehreren 1 und 0 abgerufen oder wie darf ich das verstehen?
Um also zwei Zahlen zu addieren, würde sich folgendes Programm eignen:
IN
SWP
IN
ADD
OUT
Binär:
0000
0011
0000
0100
0001
Das kannst du auf der Website direkt oben links im ROM per Edit eintragen und die Simulation per Klick auf das dritte Taktsignal starten. So sollte es aussehen:
https://imgur.com/a/UFwdGLj
Nun kannst du damit zwei Zahlen addieren. Nun probieren wir mal etwas Komplizierteres: Wir addieren zwei Zahlen und, sofern die Summe 8 ist, geben wir 5 aus. Ansonsten fragen wir wieder zwei neue Zahlen ab – so lange, bis irgendwann die Summe 8 ist. Das würde so aussehen:
IN
SWP
IN
ADD
SWP
MOV
8
SUB
JZ
12
JMP
0
MOV
5
OUT
Binär:
0000
0011
0000
0100
0011
0010
1000
0101
1011
1100
1010
0000
0010
0101
0001
Und dann zum 2. Teil der Frage: Wie arbeitet eine Programmiersprache? Wie wird es bewerkstelligt dass der PC auf die eingegebenen Zeilen reagiert?
Das geschieht genauso, wie eben beschrieben. Nun handelt es sich dabei um Maschinencode, Einsen und Nullen. Das kann man sich kaum merken, daher gibt es Programmiersprachen der zweiten Generation, sogenannte Assemblersprachen. Diese nutzen, wie man oben sieht, Symbole in Textform (z. B. IN, SWP, ADD, MOV).