Wie Computer funktionieren: Eine Erklärung von Grund auf


Beginnend mit einem Tastendruck

Du drückst die Taste ‘A’ auf deiner Tastatur.

In weniger als 1 Millisekunde erscheint das Zeichen auf dem Bildschirm.

Sieht einfach aus? In Wirklichkeit durchquert in dieser einen Millisekunde ein elektrisches Signal mindestens 6 Abstraktionsebenen, passiert dutzende Hardwarekomponenten und überquert mehrere Busse, um diese “einfache” Interaktion abzuschließen.

Das Wesen von Computern ist nicht die Berechnung, sondern die Abstraktion.

Jede Schicht verbirgt die Komplexität darunter und gibt nur eine saubere Schnittstelle an die darüberliegende Schicht weiter. Dank dieser Abstraktionen können Programmierer Code in Hochsprachen schreiben, ohne sich darum zu kümmern, wie Elektronen durch Transistoren fließen.

Heute verfolgen wir die vollständige Reise eines Tastendrucksignals und sehen, wie Computer durch Schicht um Schicht der Abstraktion eine physikalische Aktion in ein Zeichen auf dem Bildschirm verwandeln.

Erste Schicht: Vom physikalischen Signal zum Scan-Code

Bild

Was du drückst, ist kein Buchstabe, sondern ein Schalter.

Unter jeder Taste der Tastatur befindet sich ein mechanischer Schalter. Wenn du die ‘A’-Taste drückst, schließt der Schalter und Strom fließt. Das ist die unterste physikalische Realität: nur an und aus, kein ‘A’.

Die Aufgabe des Tastaturcontrollers ist es, dieses physikalische Signal in Zahlen zu übersetzen, die der Computer verstehen kann.

Wie macht er das?

Matrix-Scanning

Über 100 Tasten auf einer Tastatur. Wenn jede ihr eigenes Kabel zum Computer hätte, wäre das Tastaturkabel dicker als dein Finger. Also verwendet die Tastatur ein cleveres Design: Matrix-Scanning.

Stell dir ein Schachbrett vor, mit Zeilen und Spalten, die sich kreuzen. Jede Taste sitzt an einem Kreuzungspunkt. Der Controller versorgt schnell jede Zeile mit Strom und erkennt, ob auf jeder Spalte Strom anliegt. Wenn Spalte 5 Strom erkennt, während Zeile 3 mit Strom versorgt wird, bedeutet das, dass die Taste in Zeile 3, Spalte 5 gedrückt wurde.

Hierher kommt der Scan-Code: eine Zahl, die die Position einer Taste repräsentiert.

Das Drücken von ‘A’ könnte den Scan-Code 0x1E ausgeben. Das Loslassen von ‘A’ gibt 0x9E aus (mit einem zusätzlichen High-Bit, das “Loslassen” anzeigt).

Erste Schicht abgeschlossen: physikalische Aktion → digitale Kodierung.

Aber es ist noch nicht vorbei. Der Scan-Code befindet sich noch im internen Puffer der Tastatur und wartet darauf, gesendet zu werden.

Zweite Schicht: Vom E/A-Gerät zum Speicher

Bild

Der Scan-Code muss zur CPU gelangen, aber die CPU kann nicht einfach herumsitzen und auf Tastatureingaben warten.

Die CPU arbeitet mit Milliarden von Operationen pro Sekunde; Tastatureingaben kommen mit Dutzenden von Eingaben pro Sekunde. Wenn die CPU vor jedem Befehl prüfen würde “Gibt es eine Tastatureingabe?”, würden 99,9999 % ihrer Zeit verschwendet.

Was ist die Lösung? Der Interrupt-Mechanismus.

Interrupts: Die Hardware-Version von “Ruf mich an, wenn du bereit bist”

Die Design-Philosophie von Interrupts spiegelt den Alltag wider: Du rufst nicht alle 5 Minuten den Lieferfahrer an und fragst “Ist mein Paket angekommen?” Stattdessen ruft der Fahrer dich an, wenn er ankommt.

Nachdem der Tastaturcontroller einen Scan-Code generiert hat, sendet er ein Interrupt-Request-Signal (IRQ) an die CPU.

Dieses Signal durchläuft den Interrupt-Controller (8259A oder sein modernes Äquivalent) und erhält eine Interrupt-Nummer. Die Tastatur ist typischerweise IRQ1, Interrupt-Nummer 0x21.

Nach der Ausführung jedes Befehls prüft die CPU auf Interrupt-Signale. Wenn eines vorhanden ist, pausiert sie ihre aktuelle Arbeit und bearbeitet den Interrupt.

Die Interrupt-Vektor-Tabelle

Woher weiß die CPU, wie sie einen Tastatur-Interrupt behandeln soll?

Im Speicher gibt es eine Interrupt-Vektor-Tabelle (Interrupt Vector Table), die die Adresse der Behandlungsroutine für jede Interrupt-Nummer speichert. Sie ist wie ein Telefonbuch: Interrupt-Nummer 0x21 entspricht der Adresse des Tastatur-Handlers.

Wenn die CPU einen Tastatur-Interrupt empfängt:

  1. Schiebt den aktuellen Programmcounter (PC), Statusregister usw. auf den Stack
  2. Schlägt in der Tabelle mit der Interrupt-Nummer nach, um die Handler-Adresse zu finden
  3. Springt zum Handler und führt ihn aus

Der Tastatur-Handler liest den Scan-Code über einen E/A-Port (typischerweise 0x60) und speichert ihn dann im Tastaturpuffer im Speicher.

Zweite Schicht abgeschlossen: E/A-Ereignis → Daten im Speicher.

Jetzt liegt der Scan-Code sicher im Speicher. Aber er ist immer noch ein Scan-Code, nicht das Zeichen ‘A’.

Dritte Schicht: Vom Scan-Code zum Zeichen

Bild

Scan-Code 0x1E repräsentiert “die Position der A-Taste auf der Tastatur”, nicht das Zeichen ‘A’.

Warum? Weil dieselbe Taste auf Tastaturen in verschiedenen Ländern unterschiedliche Zeichen darstellen kann. Amerikaner drücken sie und erhalten ‘A’; Franzosen drücken sie und erhalten ‘Q’ (ihr Tastaturlayout ist anders).

Das Betriebssystem ist dafür verantwortlich, Scan-Codes in Zeichen umzuwandeln.

Das Eingabe-Subsystem

Moderne Betriebssysteme haben alle ein Eingabe-Subsystem (Input Subsystem), das folgende Aufgaben übernimmt:

  1. Einlesen von Scan-Codes aus dem Kernel-Puffer
  2. Umwandlung in Zeichen basierend auf dem aktuellen Tastaturlayout
  3. Behandlung von Modifikatortasten (Shift+A = Großbuchstabe ‘A’, Ctrl+C = Kopierbefehl)
  4. Zustellung des Zeichens an das aktive Fenster

Diese Umwandlung beinhaltet eine Tastaturlayout-Zuordnungstabelle. Die Windows-Registrierung enthält HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layouts, in der die Zuordnungen für verschiedene Sprachen gespeichert sind.

Nach der Umwandlung wird das Zeichen ‘A’ in eine Message Queue gesetzt und wartet darauf, von der Anwendung gelesen zu werden.

Dritte Schicht abgeschlossen: hardwareabhängige Kodierung → einheitliche Zeichenkodierung.

Vierte Schicht: Vom Zeichen zum Pixel

Bild

Die Anwendung empfängt das Zeichen ‘A’ und muss es auf dem Bildschirm anzeigen.

Aber was du siehst, ist kein Zeichen — es sind Pixel.

Ein Monitor versteht nur Pixel — welche Farbe jeder Punkt hat. Das Zeichen ‘A’ ist ein Muster aus einer Reihe von Pixeln, das in einer Schriftartdatei gespeichert ist.

Schriftart-Rendering

Wenn du ‘A’ eingibst, wird die Anwendung:

  1. Die Schriftartdatei suchen (z.B. Microsoft YaHei, SimSun)
  2. Die Glyphenbeschreibung für ‘A’ abrufen (Vektorkurven oder Bitmap)
  3. Die Glyphe entsprechend der Schriftgröße skalieren
  4. Rasterisieren: Die Vektorkurven in ein Pixelraster umwandeln
  5. Anti-Aliasing anwenden, um die Kanten glatter zu machen

Diese Pixeldaten werden in den Videospeicher (VRAM) geschrieben, also den Speicher auf der Grafikkarte.

Vom VRAM zum Bildschirm

Der Display-Controller auf der Grafikkarte liest 60 Mal pro Sekunde (60 Hz) Daten aus dem VRAM, wandelt sie in ein Videosignal um und sendet es an den Monitor.

Der Monitor empfängt das Signal, steuert die Farbe jedes Pixels, und du siehst das Zeichen ‘A’.

Vierte Schicht abgeschlossen: Zeichenkodierung → Pixelmatrix.

Fünfte Schicht: Wie die CPU diese Befehle ausführt

Bild

Alle oben genannten Operationen — Scannen, Interrupts, Umwandlung, Rendering — müssen letztendlich von der CPU ausgeführt werden.

Wie führt die CPU Befehle aus?

Der Befehlszyklus: Fetch-Decode-Execute

Die Ausführung eines Befehls hat drei Phasen:

  1. Fetch (Abrufen)

    • Der Programmcounter (PC) speichert die Adresse des nächsten Befehls
    • Die Adresse wird an den Speicher gesendet, der Befehl wird abgerufen
    • Der Befehl wird im Befehlsregister (IR) gespeichert
  2. Decode (Decodieren)

    • Die Steuereinheit analysiert den Opcode des Befehls
    • Bestimmt, welche Operation ausgeführt werden soll (Addition? Laden? Sprung?)
    • Bestimmt, wo sich die Operanden befinden
  3. Execute (Ausführen)

    • Die Arithmetisch-logische Einheit (ALU) führt die Berechnung durch
    • Oder greift auf den Speicher zu, um Daten zu lesen/schreiben
    • Aktualisiert den Programmcounter

Dann wiederholt sich der Vorgang.

Ein Beispiel

Angenommen, die CPU muss ADD R1, R2, R3 ausführen (die Werte in R2 und R3 addieren, in R1 speichern):

  1. Fetch: Den Maschinencode für diesen Befehl aus dem Speicher lesen
  2. Decode: Erkennen, dass dies ein Additionsbefehl ist, Operanden in R2 und R3
  3. Execute: Die ALU sendet die Werte von R2 und R3 an den Addierer, schreibt das Ergebnis in R1

Jeder Befehl wird in Nanosekunden abgeschlossen.

Fünfte Schicht abgeschlossen: Hochsprache → Maschinenbefehle → elektrische Signale.

Die Kosten der Abstraktion

Abstraktion ist nicht kostenlos.

Jede Abstraktionsebene bringt Leistungseinbußen mit sich:

  • Tastatur-Scanning: einige Mikrosekunden
  • Interrupt-Behandlung: dutzende Mikrosekunden
  • Betriebssystem-Umwandlung: hunderte Mikrosekunden
  • Schriftart-Rendering: einige Millisekunden
  • VRAM-Schreiben: einige Mikrosekunden

Zusammen ergibt das die “Eingabeverzögerung” (Input Lag), die du erfährst, typischerweise zwischen 10 und 50 Millisekunden.

Für einen normalen Menschen ist diese Verzögerung vernachlässigbar. Aber für E-Sport-Spieler ist es ein Unterschied zwischen Leben und Tod. Deshalb verwenden sie mechanische Tastaturen (schnellere Auslösung), Monitore mit hoher Bildwiederholrate (144 Hz und mehr) und kabelgebundene Verbindungen (WLAN zusätzliche Latenz).

Eine Erkenntnis

Das Wesen von Computern ist Abstraktion: Komplexität einkapseln, nur eine einfache Schnittstelle preisgeben.

Die Reise eines Tastendrucksignals:

Physikalischer Schalter → Scan-Code → Interrupt → Speicherpuffer → Zeichenkodierung → Message Queue → Schriftart-Rendering → VRAM → Pixel

Jede Schicht macht nur eines: die vereinfachte Ausgabe der darunterliegenden Schicht empfangen, verarbeiten und eine vereinfachte Schnittstelle an die darüberliegende Schicht bereitstellen.

Genau diese geschichtete Abstraktion ermöglicht es Menschen, unglaublich komplexe Computersysteme zu beherrschen.

Programmierer müssen nicht wissen, wie das Tastatur-Scannen funktioniert — sie müssen nur den Rückgabewert von getchar() lesen.

Programmierer müssen nicht wissen, wie die Grafikkarte rendert — sie müssen nur die Funktion DrawText() aufrufen.

Die Kraft der Abstraktion liegt darin, Komplexität beherrschbar zu machen.

Bild