Скачать книгу

Ordnung muss sein!

      Wenn ich mit meiner Mutter spreche, benutze ich andere Wörter, als wenn ich mit meinem Chef sprechen würde. Ich muss also immer wissen, mit wem ich es zu tun habe. Das ist in vielen Sprachen so, aber von allen Sprachen, die ich kenne, ist das am krassesten im Japanischen. Dort würde ich als Frau nicht nur andere Ausdrücke wählen als ein männlicher Kollege, wenn es sich um den Chef als Ansprechpartner handelt – es sind komplett andere Wörter, Verben und Satzbauten. Und ein bisschen ist das auch so bei Assemblersprachen!

      Es gibt eine schöne Tradition beim Coden: Das erste Programm, das man in einer neuen Programmiersprache schreibt, beginnt mit der Begrüßung »Hello World!« – und so sieht dieses Stück Code zum Beispiel in einer Assemblersprache aus:

IMG

      Abbildung 5: Beispielcode im Assembler

      Als ich Maria dieses Beispiel zeigte, hat sich mich »wie ein Auto« angeguckt. (Redewendungen wie diese lerne ich nicht nur in Assemblersprachen schnell, auch wenn ich sie im Deutschen manchmal durcheinanderbringe.) Ich konnte Marias Aufmerksamkeit aber schnell wiedergewinnen, indem ich ihr einen Gesetzestext zeigte, den sie mir »übersetzen« sollte. Alles ist nur so lange schwierig, wie es fremd ist.

      Lasst uns also mal kurz anschauen, was jede Zeile des »Hello World!«-Codes bedeutet. Keine Panik, ihr müsst euch das alles nicht merken. Aber es ist gut, alles einmal Stück für Stück durchzugehen.

IMG

      Abbildung 6: Umrechnungstabelle Dezimal, Hexadezimal und Binär

       section .data: In Assembler muss ich Sektionen definieren, die ich in meinem Programm nutze. Das schafft nicht nur Ordnung in meinem Code, sondern unterteilt diesen in Abschnitte, die die Maschine anders behandelt. In die Sektion .data schreibe ich meine statischen Daten, in diesem Fall meine Nachricht: »Hello World!«message db »Hello World!«, 0x0a: »Schreibe den Text ›Hello World!‹ in die Schublade message, und füge einen Zeilenumbruch am Ende ein (0x0a).« Damit das klappt, muss ich die Größe meiner Nachricht in Bytes ermitteln, das tue ich mit db (define bytes). 1 Byte = 8 Bits, wobei 1 Bit entweder 1 (EINS) oder 0 (NULL) ist. Der Zeilenumbruch hat das Hexadezimalzeichen 0x0a. Das Hexadezimalsystem wird für die Verwaltung des Binärsystems verwendet, um sich etwas Platz zu sparen. Statt achtstellige Binärzahlen zu schreiben, schreibe ich 0x und dann die zweistellige Hexadezimalzahl. Assembler ist nun mal sehr »maschinig«, es wird so wenig Text wie möglich geschrieben, umso mehr in Zahlen und Hexadezimalzahlen, deren Übersetzung in Tabellen zum Nachschlagen gespeichert ist. Hier wird die Arbeit der Maschine einfach gemacht und nicht dem Menschen.message_length equ $-message: »Reserviere genug Platz für meinen Text.« Dieser Schritt ist notwendig, damit der notwendige Speicherplatz für meinen Text reserviert wird. Denkt an meine Sommerklamotten und an die linke Schublade im neuen Kleiderschrank!

       section .text: In der Sektion .text wird mein Programm geschrieben, damit sage ich der Maschine: »Hier kommt mein Code!«

       global start und start: Diese Befehle nutze ich, um der Maschine zu sagen: »Ab hier beginnt die Ausführung des Programms.«mov eax, 4: Damit sage ich der Maschine: »Hole dir die Aktion 4 und kopiere sie in eax.«— Die Aktion mit dem Wert 4 steht für den System Call »write«, also »schreiben«. Die System Calls sind die Aktionen, die mein System ausführen soll, meistens Lesen, Schreiben, Beenden, Öffnen, Erstellen etc. In Assembler hat jeder System Call einfach eine Nummer, ich schreibe die gewünschte Aktion also nicht in Textform, sondern als Nummer. Dafür gibt es eine Tabelle, in der steht, welche Aktion welche Nummer hat.— Das Register eax ist das erste in der Reihenfolge der Register (die Bezeichnungen der Register sind ebenfalls festgelegt), und dahin soll mein »write« zwischengelagert werden. Damit die Aktion richtig ausgeführt werden kann, muss ich noch ein paar Parameter definieren. Ich muss angeben, was mein System wohin schreiben soll und wie groß dieser Text ist. Das mache ich in den nächsten Zeilen.mov ebx, 1: »Hole dir Aktion 1 (das ist die Standard-Anzeige, kurz: stdout), und kopiere sie in ebx (das ist das zweite Register).«mov ecx, message: »Hole dir den Inhalt aus der Schublade message und kopiere ihn in ecx (das dritte Register).«mov edx, message_length: »Lese die Größe der Nachricht aus der Schublade message_length und trage sie in edx (das vierte Register).« Damit reserviere ich genug Platz im Speicher, damit der Text richtig und vollständig angezeigt werden kann.int 0x80: »Hiermit ist die Kopieraufgabe erledigt, gehe zurück zum Hauptcode.«Mit den letzten drei Befehlen (mov eax, 1 / mov ebx, 0 / int 0x80) sage ich der Maschine: »Beende das Programm.«

      Wie ihr seht, wird in diesem Assemblerprogramm der Befehl MOV häufig verwendet. MOV ist tatsächlich einer der Grundbefehle in Assembler, mit dem Inhalte von Schublade zu Schublade bewegt werden. Der Befehl selbst verweist auf einen binären Code. Wenn ich also MOV schreibe, sucht die Maschine aus der MOV-Schublade den binären Code raus und setzt diesen um. Text kann sie nicht verstehen, nur Einsen und Nullen. Alles, absolut alles, was ich eintippe, hat eine entsprechende Übersetzung in Nullen und Einsen. Denn am Ende des Tages beziehungsweise Codes geht es um »Strom an«, »Strom aus« – that’s it!

      Das Assembler-Beispiel sollte euch zeigen, wie man mit dem Programmieren angefangen hat. Heute ist das sehr viel einfacher geworden. Die Komplexität hat deutlich abgenommen, und in der Zukunft werden die Programmiersprachen so intuitiv sein, dass fast jeder Mensch sie bedienen kann, egal ob Informatiker oder nicht.

      Höhere Sprachen: Mehr was für Menschen

      Die zweite Art der Programmiersprachen nennt man »höhere« Sprachen. Vermutlich weil wir selbst uns an dieser »höheren« Stelle sehen im Vergleich zu den Maschinen, die unter im Keller beziehungsweise Maschinenraum vor sich hin brummen. Auf jeden Fall sind die höheren Programmiersprachen näher an uns Menschen als an den Maschinen. Das hat den Vorteil, dass die Sätze/Befehle für uns viel besser verständlich sind als beim Assembler. Damit nun aber auch die Maschinen diese Sätze verstehen, bauen wir kleine Übersetzer ein, die bereits erwähnten Compiler. Es gibt hier also zwei Stufen der Übersetzung: Einmal durch uns – von Menschensprache in eine höhere Programmiersprache – und einmal durch den Compiler – von der höheren Programmiersprache in Maschinensprache, also in Binärcode. Die Aufgabe des Compilers besteht überwiegend darin, die Syntax zu prüfen, zu analysieren und zu optimieren, und dann einen Code daraus zu erzeugen, den die Maschine versteht.

      Compiler werden auch von Menschen gebaut, klar. Man kann ihre Existenz insofern auch als eine Art Maßnahme zur Effizienzsteigerung betrachten: Ein paar Programmierer setzen sich hin und entwickeln einen Compiler, mit dem man mehrere höhere Sprachen in Maschinensprache übersetzen kann, und das spart den anderen Programmierern lästige Arbeit. So kann sich jeder auf seine Aufgabe konzentrieren: Die einen schreiben den Quelltext in menschenverständlicher Form, die anderen (die Compiler) erzeugen den Binärcode für die Maschine. Dass die Befehle im Binärcode für uns nicht mehr lesbar sind (eine lange, lange Serie von Einsen und Nullen), muss uns nicht weiter stören.

      Es gibt heute viele unterschiedliche dieser höheren Programmiersprachen, zum Beispiel BASIC, C, C++, C#, PHP, SQL, Python, Java, JavaScript, Scratch etc. Welche man wählt, hängt in der Regel von dem Problem ab, das man lösen möchte. Unterschiedliche Sprachen eignen sich zur Lösung unterschiedlicher Probleme, und alle haben ihre Vor- und Nachteile. Für Webanwendungen zum Beispiel, also um Webseiten zu programmieren, eignen sich JavaScript und Java sehr gut. Um Hardware zu programmieren, eignen sich eh C oder C++. Um Datenbanken zu erstellen, zu befüllen und wieder auszulesen, eignet sich SQL. Und um die Steuerung von kleinen LEGO-Robotern zu ermöglichen, eignet sich Scratch, die extra für Kinder und Jugendliche entwickelt wurde.

      Schauen wir uns doch mal ein Beispiel aus der Programmiersprache C++ an und beginnen auch hier wieder mit einem freundlichen »Hello World!« auf unserem Bildschirm.

      Dafür brauchen wir folgenden Quellcode:

IMG

      Abbildung

Скачать книгу