Kapitel 3
Die ursprüngliche Software (1950-1960)
Während die Hardware die physische Struktur der ersten Computer darstellte, stellte die Software die Intelligenz dar, die sie belebte, und ermöglichte die Umwandlung elektronischer Schaltkreise in Berechnungs- und Informationsverarbeitungswerkzeuge. In den frühen Jahren der Informatik war die Softwareentwicklung eine Pioniertätigkeit, die oft eng mit detaillierten Kenntnissen der Hardwarearchitektur verbunden war. In diesem Kapitel werden wir frühe Formen von Software untersuchen, von Maschinen- und Assemblersprachen bis hin zu frühen Programmiersprachen auf hoher Ebene und rudimentären Betriebssystemkonzepten.
3.1 Maschinensprache:
Direkte Kommunikation mit der Hardware
Die grundlegendste Form von Software ist Maschinensprache . Dies ist die Muttersprache, die direkt von der Zentraleinheit (CPU) eines Computers verstanden wird. Jeder CPU-Typ verfügt über seine eigene spezifische Maschinensprache, die aus einer Folge binärer Anweisungen (Folgen aus Nullen und Einsen) besteht. Jede maschinensprachliche Anweisung entspricht einer elementaren Operation, die die CPU ausführen kann, wie zum Beispiel:
- Arithmetische Operationen: Zahlen addieren, subtrahieren, multiplizieren, dividieren.
- Logische Operationen: Führen Sie boolesche logische Operationen (AND, OR, NOT) an Bits durch.
- Datenübertragung: Daten zwischen Speicher und CPU-Registern verschieben.
- Flusskontrolle: Ändern Sie die Reihenfolge, in der Anweisungen ausgeführt werden (bedingte und bedingungslose Sprünge).
Das direkte Programmieren in Maschinensprache war aus mehreren Gründen eine äußerst mühsame und komplexe Aufgabe:
- Lese- und Schreibschwierigkeiten: Binäre Sequenzen sind für Menschen schwer zu interpretieren und zu merken. Ein einfaches Programm erfordert möglicherweise lange und komplizierte Folgen von Nullen und Einsen.
- Abhängigkeit von der Hardware-Architektur: Maschinensprache ist spezifisch für eine bestimmte CPU-Architektur. Ein Programm, das für einen Computertyp geschrieben wurde, konnte nicht auf einem anderen Computertyp mit einer anderen Architektur ausgeführt werden.
- Hohes Fehlerrisiko: Die direkte Manipulation von Binärsequenzen machte es extrem einfach, Tipp- oder Logikfehler zu machen.
- Debugging-Schwierigkeit: Das Finden und Korrigieren von Fehlern in einem in Maschinensprache geschriebenen Programm war ein langer und frustrierender Prozess.
Trotz dieser Schwierigkeiten mussten die frühen Programmierer zwangsläufig auf diesem Niveau arbeiten, um die ersten Computer zum Laufen zu bringen. Die Programmierung in Maschinensprache erforderte ein tiefes Verständnis der Computer-Hardwarearchitektur und viel Liebe zum Detail.
3.2 Assemblersprache:
Ein Schritt in Richtung Abstraktion
Um die Programmieraufgabe zu vereinfachen, wurde die Assemblersprache entwickelt.
Diese Sprache ist eine symbolische Darstellung der Maschinensprache. Anstatt binäre Sequenzen zu verwenden, verwendet die Assemblersprache Mnemoniken (kurze Abkürzungen) zur Darstellung von Anweisungen in Maschinensprache und symbolische Namen zur Darstellung von Speicheradressen.
Beispielsweise könnte eine maschinensprachliche Anweisung zum Addieren zweier Zahlen in Assemblersprache mit einer Mnemonik wie ADD gefolgt von den Namen der Register oder Speicheradressen dargestellt werden, die die zu addierenden Zahlen enthalten.
Um ein in Assemblersprache geschriebenes Programm auf einem Computer auszuführen, war ein spezielles Programm namens Assembler erforderlich. Der Assembler übersetzt jede Assembler-Anweisung in die entsprechende Maschinensprache-Anweisung.
Die Verwendung der Assemblersprache bot gegenüber der direkten Maschinensprachenprogrammierung mehrere Vorteile:
- Bessere Lesbarkeit und Beschreibbarkeit: Mnemoniken waren leichter zu merken und zu interpretieren als binäre Sequenzen.
- Verwendung symbolischer Namen: Ermöglicht Programmierern, auf Speicheradressen und andere Entitäten zu verweisen, indem sie symbolische Namen anstelle numerischer Adressen verwenden, was die Speicherverwaltung vereinfacht und das Fehlerrisiko verringert.
- Erhöhte Produktivität: Die Assemblerprogrammierung war schneller und weniger fehleranfällig als die Maschinensprachenprogrammierung.
Allerdings blieb die Assemblersprache immer noch eine Low-Level-Sprache, die eng mit der Hardwarearchitektur des Computers verbunden war.
Programmierer mussten immer noch ein gutes Verständnis für das Innenleben der CPU und des Speichers haben. Darüber hinaus konnte ein in Assembler geschriebenes Programm für eine bestimmte Architektur nicht einfach auf eine andere portiert werden.
3.3 Die ersten höheren Programmiersprachen:
Auf dem Weg zur Hardware-Unabhängigkeit
Die wachsende Komplexität der Probleme, die Computer lösen wollten, und die Schwierigkeit der Programmierung in Low-Level-Sprachen führten zur Entwicklung von High-Level-Programmiersprachen . Diese Sprachen wurden so konzipiert, dass sie der menschlichen Sprache näher kommen und unabhängiger von der spezifischen Hardwarearchitektur des Computers sind. Ein einzelner Befehl in einer Hochsprache könnte mehreren Anweisungen in Maschinensprache entsprechen.
Um ein in einer Hochsprache geschriebenes Programm auszuführen, war ein spezielles Programm namens Compiler oder Interpreter erforderlich. Ein Compiler übersetzt das gesamte Hochsprachenprogramm vor der Ausführung in Maschinensprache (oder eine Zwischensprache). Ein Interpreter hingegen übersetzt und führt das Programm Zeile für Zeile aus.
In den 1950er Jahren entstanden einige der ersten und einflussreichsten Hochprogrammiersprachen:
- FORTRAN (FORMELÜBERSETZUNG): FORTRAN wurde ab 1954 von einem Team unter der Leitung von John Backus bei IBM entwickelt und speziell für wissenschaftliche und technische Anwendungen entwickelt, die intensive numerische Berechnungen erforderten. FORTRAN bot eine Syntax, die eher der mathematischen Notation ähnelte, und stellte spezifische Konstrukte für die Bearbeitung von Arrays und Matrizen bereit.
- Sein Erfolg stellte sich in der wissenschaftlichen und technischen Gemeinschaft sofort ein, und FORTRAN wird auch heute noch in einigen Bereichen der Forschung und Entwicklung eingesetzt. Seine Einführung stellte einen grundlegenden Schritt zur Vereinfachung der wissenschaftlichen Programmierung dar.
- COBOL (COMmon Business-Oriented Language): COBOL wurde ab 1959 von einem von Grace Hopper geleiteten Komitee entwickelt und war für Geschäfts- und Datenverarbeitungsanwendungen konzipiert. Das Ziel bestand darin, eine Sprache zu schaffen, die auch für Nicht-IT-Experten, wie Manager und Geschäftsanalysten, leicht zu verstehen und zu verwenden ist. COBOL legte Wert auf Lesbarkeit und stellte spezifische Konstrukte für die Verwaltung großer Datenmengen, die Erstellung von Berichten und die Interaktion mit Dateien bereit. COBOL entwickelte sich schnell zur vorherrschenden Sprache für Geschäftsanwendungen und erfreut sich seit Jahrzehnten einer beträchtlichen Bedeutung. Viele wichtige Legacy-Unternehmenssysteme sind auch heute noch in COBOL geschrieben.
- LISP (LISt Processing): LISP wurde 1958 von John McCarthy am MIT entwickelt und war für die Forschung im Bereich der künstlichen Intelligenz sowie für die Manipulation von Symbolen und Listen konzipiert. Seine Syntax, die auf der umfassenden Verwendung von Klammern basierte, unterschied sich grundlegend von der von FORTRAN und COBOL. LISP führte innovative Konzepte wie Rekursion und die Behandlung von Funktionen als Daten ein. Obwohl LISP in anderen Bereichen nicht die Popularität von FORTRAN und COBOL erreicht hat, hatte es einen erheblichen Einfluss auf die Forschung im Bereich der künstlichen Intelligenz und die Entwicklung anderer Programmiersprachen.
Die Entwicklung dieser frühen Hochsprachen stellte für Programmierer eine enorme Vereinfachung dar, da sie sich auf die Logik des zu lösenden Problems konzentrieren konnten und nicht auf die Details der Hardwarearchitektur.
Dies führte zu einer höheren Produktivität und der Fähigkeit, komplexere Probleme mit Computern zu lösen.
3.4 Frühe Betriebssystemkonzepte (Stapelverarbeitung)
In den frühen Jahren der Informatik gab es keine komplexen Betriebssysteme, wie wir sie heute kennen. Die Interaktion mit dem Computer erfolgte oft direkt und der Programmierer musste alle Ressourcen der Maschine manuell verwalten. Da Computer jedoch immer leistungsfähiger und komplexer wurden, entstand der Bedarf an Software, die Hardwareressourcen verwalten und die Programmausführung vereinfachen konnte.
Eine der frühesten Formen der Auftragsverwaltung auf Computern war die Stapelverarbeitung . Bei diesem Ansatz wurde eine Reihe von Jobs (d. h. auszuführende Programme mit ihren Eingabedaten) in einem „Batch“ gesammelt. Der Computerbediener lud den Stapel von Jobs in den Computer, der sie nacheinander nacheinander ausführte, ohne dass der Programmierer während der Ausführung direkt eingreifen musste. Die Ergebnisse jedes Auftrags wurden dann als Ausgabe ausgegeben (z. B. auf Magnetband oder Drucker).
Die Stapelverarbeitung hatte einige Vorteile:
- Höhere Effizienz: Dadurch konnte der Computer kontinuierlicher genutzt werden, wodurch die Ausfallzeiten zwischen der Ausführung eines Jobs und eines anderen reduziert wurden.
- Vereinfachung der Verwaltung: Der Bediener musste nur die erste Charge laden und dann die Ergebnisse sammeln, ohne ständig mit dem Computer interagieren zu müssen.
Die Stapelverarbeitung hatte jedoch auch Einschränkungen:
- Mangelnde Interaktivität: Der Programmierer konnte während der Ausführung nicht mit dem Programm interagieren. Wenn ein Fehler auftrat, mussten Sie warten, bis der Job abgeschlossen war, um die Ausgabe zu analysieren.
- Lange Wartezeiten: Wenn ein Job lang war, mussten andere Jobs im Stapel warten, bis er abgeschlossen war.
Trotz dieser Einschränkungen stellte die Stapelverarbeitung einen ersten Schritt in Richtung der Entwicklung moderner Betriebssysteme dar und führte das Konzept der automatischen Verwaltung der Programmausführung ein.
3.5 Herausforderungen und Innovationen in der frühen Softwareentwicklung
Die Softwareentwicklung war in den Anfangsjahren der Informatik eine äußerst anspruchsvolle Tätigkeit. Programmierer standen vor zahlreichen Herausforderungen:
- Teure und begrenzte Hardware: Die Hardwareressourcen früher Computer waren knapp und teuer. Programmierer mussten ihren Code sorgfältig optimieren, um den verfügbaren Speicher und die Rechenleistung optimal zu nutzen.
- Rudimentäre Entwicklungstools: Es gab keine integrierten Entwicklungsumgebungen, ausgefeilten Debugger und Softwarebibliotheken, an die wir heute gewöhnt sind. Die Programmierung war oft ein manueller und sorgfältiger Prozess.
- Mangelnde Standardisierung: Es gab keine allgemein akzeptierten Standards für Programmiersprachen und Hardwareschnittstellen, was die Softwareportabilität erschwerte.
- Begrenzte Entwicklergemeinschaft: Die Programmiergemeinschaft war klein und Programmierkenntnisse und -techniken entwickelten sich ständig weiter.
Trotz dieser Schwierigkeiten zeigten Softwarepioniere große Kreativität und Einfallsreichtum bei der Entwicklung der ersten Programme und legten den Grundstein für die Disziplin Software Engineering. Obwohl die Einführung von Hochsprachen zunächst mit Skepsis von einigen begrüßt wurde, die die Kontrolle durch Niedrigsprachen bevorzugten, erwies sie sich als entscheidender Schritt, um die Programmierung zugänglicher und produktiver zu machen.
Die frühe Software der 1950er Jahre war geprägt vom Übergang von der Programmierung direkt in Maschinensprache hin zur Verwendung von Assemblersprachen und vor allem der ersten Hochprogrammiersprachen wie FORTRAN, COBOL und LISP. Diese Sprachen stellten eine wichtige Abstraktion von der Hardware dar, vereinfachten die Programmieraufgabe und ebneten den Weg für neue Anwendungen für Computer. Parallel dazu entstanden erste Betriebssystemkonzepte wie die Stapelverarbeitung, die darauf abzielten, die Effizienz bei der Nutzung wertvoller Hardwareressourcen zu verbessern. Die Herausforderungen bei der Softwareentwicklung waren beträchtlich, aber der Einfallsreichtum und die Entschlossenheit der frühen Programmierer legten den Grundstein für die anschließende Explosion der Softwarewelt.