In der Serie “Wie Rechner rechnen” habe ich versucht, die physikalischen Grundlagen eines Computers zu erklären und darzulegen, was in so einem Ding überhaupt im Inneren vorgeht. Speziell im letzten Teil haben wir dabei betrachtet, wie ein Computer nun genau Befehle ausführt. Heute nun soll es darum gehen, wie man diese Befehle eigentlich auf vernünftige Weise in den Rechner hineinbekommt (die Wünsche einiger Leser nach mehr Details zu modernen Techniken bei der Befehlsausführung habe ich vermerkt und reiche sie noch nach – ich möchte nur vorher einige Dinge einführen, die dafür nötig sind).
Fassen wir noch einmal kurz zusammen: irgendwo im Computer, meist im Cache oder im Arbeitsspeicher, stehen Instruktionen – Bitketten, die eine auszuführende Aktion codieren. Eine Instruktion setzt sich aus dem Opcode, der eigentlichen Aktion, und den Operanden, also den zu benutzenden Daten, zusammen. Das fiktive Beispiel aus dem letzten Beitrag war die Instruktion “0110110101”, welche in die Bestandteile 0110, 11 und 0101 unterteilt werden kann, wobei “0110” der Opcode ist und die Anweisung “addiere einen festen Wert zu dem in einem Register gespeicherten Wert” codiert, “11” das zu benutzende Register (im Beispiel den Akkumulator) beschreibt und “0101” schließlich den festen Wert, hier eine 5, codiert. Zusammengenommen ergibt die Bitkette also die Instruktion “addiere den Wert 5 auf den im Akkumulator gespeicherten Wert” (ich weiße – nur zur Sicherheit – noch einmal darauf hin, dass das Beispiel rein fiktiv ist und keine Entsprechung in der Realität hat). Man sagt, die Instruktionen sind im Maschinencode geschrieben; mehrere Instruktionen zusammen bilden ein Programm.
Nun könnte man einen Computer natürlich programmieren, indem man viele dieser Instruktionen von Hand schreibt, in der richtigen Reihenfolge aneinanderreiht und dann in den Speicher eines Computers lädt (wie heutzutage das Laden funktionieren würde, ist noch einmal eine Sache für sich und eine Variante des bekannten Henne-Ei-Problems). In den Anfangsjahren der Informatik wurde das tatsächlich auch noch so gemacht; die Bitketten konnten allerdings nicht immer einfach komfortabel am Rechner eingegeben werden, sondern mussten teilweise noch manuell auf ein Trägermedium transferiert werden – die allseits bekannten Lochstreifen und Lochkarten. Lochstreifen (siehe Abbildung; Quelle: Wikipedia) waren lange Streifen aus Papier oder Kunststoff, auf welche Informationen in Form von Bitketten gespeichert wurden, wobei ein Loch etwa der logischen “1” entsprach und kein Loch entsprechend der logischen “0”. War der Lochstreifen breit genug für 8 nebeneinanderstehende Löcher, so konnte eine Bitkette der Länge 8 in jeder Zeile gespeichert werden. Eine Lochkarte war im Grunde das gleiche, nur in der Länge begrenzt (übrigens gab es Lochkarten und -streifen nicht erst mit dem Aufkommen von Computern – bereits vorher wurden sie eingesetzt, zum Beispiel in den bekannten Jacquardwebstühlen). “Programmiert” wurde also, indem man kleine Löcher in Papier gebohrt hat.
Wer jetzt der Meinung ist, dass ein derartiges Vorgehen höchst umständlich anmutet, hat natürlich vollkommen recht; in den Anfangsjahren gab es dazu aber keine Alternative. Dennoch war man natürlich bemüht, ein besseres Verfahren zu finden, da das Stanzen von Löchern doch ein wenig umständlich und der Code auch ziemlich schlecht zu lesen war. Hinzu kam, dass jeder Prozessortyp seine ganz eigene Codierung der Instruktionen hatte – Programme waren also nicht wirklich gut auf andere Architekturen portierbar.
Die Lösung des Problems wurde in den 1950er Jahren entwickelt: die Assemblersprachen1. Eine Assemblersprache ist in ihrer einfachsten Form nichts weiter als eine Möglichkeit, Maschinencode (also Instruktionen) in einer besser lesbaren Form zu notieren. Obgleich es unterschiedliche Arten gibt, Assemblercode niederzuschreiben, ähneln sich Assemblersprachen in vielen Punkten. So werden die Opcodes, die ja nichts anderes als binäre Zahlen sind, durch besser verständliche (und vor allem besser merkbare) Wörter ersetzt. Aus mir nicht näher bekannten Gründen (ich tippe auf Speicherplatzersparnis) wurden dabei nicht irgendwelche Wörter gewählt, sondern möglichst kurze, eindeutige und natürlich englische. Die Anweisung “addiere” wird folgerichtig üblicherweise mit add abgekürzt, Subtrahieren mit sub
und die Anweisung zum Verschieben von Speicherinhalten mit mov
. In Anlehnung an die Funktion der Wörter, nämlich das Merken der komplizierten Opcodes zu vereinfachen, werden sie übrigens auch Mnemonics genannt. Hinter dem Wort für die Aktion folgen nun die dazugehörigen Operanden; auch diese können über Mnemonics dargestellt werden, etwa im Fall von Registern; Speicheradressen und Zahlen lassen sich dagegen ganz normal im bekannten Dezimalsystem angeben.
Kommentare (20)