Der Computer ist ein fortlaufendes, gemeinschaftliches
Projekt von
Generationen von Wissenschaftlern,
Ingenieuren und Software-Entwicklern, wobei jede
Generation auf den Errungenschaften
der Vergangenheit aufbaut.
Diese Prinzipien gelten zwar für viele technische
Leistungen, finden sich aber nirgends so wie beim
Computer
verdichtet und in solch
rasanter Abfolge.
Der Computer ist damit wahrhaftig die
höchste kulturelle, wissenschaftliche und
technische Errungenschaft der Menschheit.
(Leider hinken seine Nutzer, vor allem die
Generation Web 2.0, ihm größtenteils weit
hinterher und verwenden ihn entsprechend.)
Dieses Kapitel wird, als ein Beispiel für die
fortlaufenden Verbesserungen, die Entwicklung
von
Programmiersprachen erklären.
Der Programmspeicher sehr früher Computer
war nur ein
ROM (engl. "read-only memory"
= "Nur-Lesen-Gedächtnis"), und zwar in Form
von
Lochkarten und später
Lochstreifen.
Die Löcher in der Pappkarte oder im
Papierstreifenband erlaubten es
Elektroden
(Metallkugeln oder -sfifte), die unter der Karte
bzw. dem Streifen liegende andere Elektrode
(ein Metallrad oder -plättchen) zu kontakten,
was ein
Bit in der Steuereinheit setzte.
Der
Programmzeiger wurde dadurch erhöht,
dass ein
Motor die Karte oder den Streifen
um eine Lochreihe weiterzog.
Das
Programmieren erfolgte dadurch, dass man
sorgfältig die Löcher in die Karte oder den Streifen
stanzte, wobei man sich an Referenz-Tabellen
orientierte, die angaben, mit welchem Bit-Muster
der gewünschte Effekt zu erzielen war.
Diese Programme wurden also direkt im
Maschinencode geschrieben, den reinen Bits,
was eine harte Arbeit bedeutete, nur um,
verglichen mit modernen Programmen,
geradezu rudimentäre Aufgaben zu erledigen.
Aber es gab Leute, die darin so gut wurden,
und genug
Leidenschaft entwickelten,
um auf diese Art immer längere, immer
komplexere Programme zu schreiben.
Sie schafften es, dass der Computer die Eingaben
von einfachen
Tastaturen akzeptierte, den
eingegebenen
Text auf automatisch gestanzten
Lochstreifen
speicherte, solchen Text wieder
vom Lochstreifen
lesen konnte, um ihn in
der nächsten Sitzung
fortzuschreiben ...
... und schließlich, dass dieser Text vom Programm
analysiert wurde und nach einigen gekonnten
Berechnungen aus diesem Text ein
neuer
Maschinencode erzeugt werden konnte
— an diesem Punkt war mit dem
Assembler
die erste Programmiersprache geboren, und
das Programmieren in Maschinencode
wurde über Nacht
überflüssig.
Programmieren in Assembler bedeutete nun,
dass man den
Quellcode als Textbefehle
auf einer Computertastatur schrieb.
Dieser Text wird dann von dem
Assembler-
Compiler-Programm gelesen,
das aus ihm den Maschinencode erzeugt,
der auf den Lochstreifen gestanzt wurde.
Auch
heute noch hat jeder Computer und
jeder Mikrocontroller seinen
eigenen
Assembler (nur wird nicht mehr
auf Lochstreifen gespeichert),
auf dem alles weitere aufbaut.
Da der Maschinencode für jeden
Miktrocontroller und Miktroprozessor
unterschiedlich ist, unterscheiden sich
auch die Assembler voneinander.
Assembler ist also mehr ein
Konzept,
keine einzelne Programmiersprache.
Assemler verwendet
Befehlskürzel,
die für ein oder aber auch mehrere
Maschinencode-Befehle stehen können.
Nachschlagetabellen sagen dem
Programmierer, wie viele Prozessorzyklen
jeder Assembler-Befehl tatsächlich benötigt.
Um dir mal einen Eindruck zu vermitteln,
hier vier
typische Assembler-Befehle:
MOV A,B
= "move from A to B" (engl. "beweg von A nach B")
Kopiert das resultierende Register-Byte,
das von der Adresse A gelesen wurde,
in den Speicher bei Adresse B.
(Manche Assembler schreiben es MOV B,A.)
ADD 7
Addiert (engl. "add") die Konstante 7
zum letzten Ergebnis der ALE.
NOP
= "no operation" (engl. "keine Operation")
Der
NOP-Befehl wird verwendet, um den
Computer einen Takt lang warten zu lassen,
etwa um ihn mit E/A-Datenprotokollen
zu synchronisieren, die langsamer laufen.
JNZ l1
= "
jump (on)
non-zero"
(engl. "spring, [wenn] nicht null")
Wenn das letzte Ergebnis der ALE nicht "0" war,
wird der Programmzeiger auf die Adresse gesetzt,
die der Compiler aus dem Label "l1" berechnet.
Labels werden als Quellcode-Textzeilen gesetzt
und können sehr bequem anstelle von festen
Adress.Konstanten verwendet werden.
Das "l1" von oben etwa könnte man mit der
folgenden Zeile (zwischen Befehlszeilen) setzen:
l1:
Auch führten Assembler bereits
Variablen ein,
Namen für Seicher-Adressen, die erst der
Compiler konkret zuordnet.
Und wieder gab es Manche, die so gut darin
wurden und genug Leidenschaft mitbrachten, dass
sie mit dem Assembler den nächsten Schritt, die
eigentlichen
Programmiersprachen, entwickelten.
Diese
parsen mehr oder weniger einfach lesbare
Quellcode-Zeilen
variabler Länge, die oft für
dutzende Zeilen Assemblercode stehen oder gar
für ganze Assembler-
Unterprogramme.
Sie führten auch viele
Abstraktionen ein,
die, verglichen mit Assembler, viel näher an
dem sind, wie wir Menschen gewohnt sind zu
denken, etwa mit
sprachlicher Grammatik
(beispielsweise wenn-dann-sonst und Schleifen)
oder in
mathematischen Formeln.
Die eigentlichen Programmiersprachen laufen
zudem auf
verschiedenen Mikroprozessortypen.
Jeder Typ braucht seinen eigenen Compiler für
die Programmiersprache, so dass eine Zeile wie
"a = b + c*d" je nach Mikroprozessor recht
unterschiedlich umgesezt wird (Maschinencode),
die Zeile selbst bleibt aber in der gegebenen
Programmiersprache stets
gleich und hat
auch überall denselbe definierte Wirkung.
Es sind
viele Programmiersprachen entwickelt
worden, alle mit ihren eigenen Features,
Ideen, Stärken — und Schwächen.
Nur wenige erlangten weite Verbreitung,
wobei ihr Erfolg nicht immer proportional
zu ihrer allgemeinen
Qualität war,
sondern oft nur das Ergebnis von
Großkonzern-Marktkämpfen mit
ihrer geballten Marketing-Macht.
So wurde die mit Abstand
einflussreichste
Programmiersprache ausgerechnet eine
schlicht "
C" genannte, vergleichsweise
kryptische Sprache, die so un-clever ist wie
ihr Name und voller Fallstricke steckt,
die schon zahllose katastrophale
Softwarefehler bedingt haben.
Alle frühen Programmiersprachen waren noch
ziemlich anstrengend in der Benutzung, aber
wieder gab es manche Leute, die sie nutzten,
um
neue, bessere Programmiersprachen
zu implementieren, die immer
komfortablere
Features hinzufügten und die Fallstricke und
Fehler der alten vermieden.
Wirklich? Leider nicht ganz. Tatsächlich bestand
die nächste Generation oft nur aus
reformierten
Versionen der alten Sprachen, so folgten auf C
etwa
C++ und
C#, aber sie behielten die
meisten Nachteile der alten Sprachen bei.
Auch führten neue Sprachen immer
exzentrischere
Features ein, die von akademischen Theoretikern
erdacht worden waren und dann heftig vermarktet
wurden, tatsächlich aber nur dazu führen, dass
Programme
langsamer laufen, immer mehr
RAM und
Festplattenplatz vergeuden und
nicht wirklich die Produktivität verbessern.
Aber Marketing zieht, weil es als professionelle,
das ganze Jahr aktive Großindustrie auf dem
hauptberuflichen Missbrauch von Psychologie
basiert, so dass dir viele Leute begegnen werden,
die, obwohl das Gegenteil wissenschaftlich gut
belegt ist, eisern der Meinung sind, dass
etwa
objekt-orientierte Programmierung
eine richtig tolle Sache sei.
Als das
Internet ernsthaft wichtig wurde,
kamen spezielle Programmiersprachen auf,
etwa
PHP zum Programmieren von Software
für Webserver, die sichere Logins ermöglicht,
Nutzerdaten verwaltet und vieles mehr,
und
JavaScript zum Programmieren von
Software. für Webbrowser, die die angezeigte
Website dynamisch auf Nutzereingaben
reagieren lässt oder Seiten-Elemente animiert.
So ziemlich alle davon basieren auf C,
haben aber recht tiefgreifende Reformen
vorgenommen, die sie sehr viel
komfortabler
machen — allerdings laufen ihre Programme
langsamer als in C geschriebene Programme.
Der Grund ist, dass der Programmierer in C
festlegen muss, wie viele
Bytes eine Variable
belegen soll (
typisierte Variablen) und diese
Einstellung im gesamten Code genauestens
einhalten muss — in PHP, JavaScript und Co
jedoch können Variablen jederzeit ihren Typ
ändern, und das Programm selbst übernimmt
die Überprüfungen und Konvertierungen zur
Laufzeit, und zwar
jedesmal, wenn eine
Variable gelesen oder geschrieben wird.
Und wieder werden immer weitere neue
Programmiersprachen entwickelt, so wie
Eas,
das in seiner aktuellen Eas-4B-Umsetzung
nach JavaScript kompiliert, weswegen es noch
ein wenig langsamer ist als JavaScript, dafür aber
als wirklich von Grund auf
neu erschaffene
Sprache keine der üblichen Fallstricke und
Schwachpunkte aller C-Ableger hat und zudem
in der Anwendung maximalen
Komfort bietet.
Die Geschichte geht weiter, und ich denke,
dass das größte Potenzial darin liegt,
den Ballast der alten Sprachen endlich
abzuschütteln, indem sie durch
Maschinencode-Compiler für moderne
Sprachen
vollständig ersetzt werden.
Warum? Weil mir meine Erfahrung mit großen
Softwareprojekten immer und immer wieder
gezeigt hat, dass die größten Fortschritte nur
dadurch zu erzielen sind, dass man wieder
ganz von vorn mit einem leeren Blatt
beginnt, nachdem man von der Arbeit mit
dem alten Code ein paar Generationen
bzw. Versionen hinweg gelernt hat.
Beispielsweise verwendete eine Firma ein
wichtiges Mikrocontrollerprogramm, das
über die Jahre von mehreren Programmierern
immer weiter verbessert worden war. Als man
es mir übergab, warf ich es in den Papierkorb
und schrieb es in nur zwei Wochen ganz neu
— meine Version ist mehr als
1000-mal
schneller, hat mehr Features und läuft
(im Gegensatz zu dem alten Programm)
hundertprozentig zuverlässig.