Programmiersprache Pascal

Arbeitsschritte beim Implementieren von Programmen

Beim Implementieren von Programmen laufen folgende wesentliche Schritte ab:
Editieren
Der Quelltext kann mit einem beliebigen Texteditor erstellt und modifiziert werden.
Moderne Programmiersysteme bieten oft eine integrierte Umgebung: Es kann aus dem Editor heraus übersetzt und getestet werden.
Übersetzen
Bei höheren Programmiersprachen prinzipiell erforderlich.
Zum Einsatz kommen entweder Compiler oder Interpreter oder eine Kombination von beiden.
Verbinden
Bei Einsatz eines Compilers erforderlich.
Die vom Programmierer geschriebenen Programmteile werden vom Verbinder (Binder, linker, linkage editor) mit Teilen aus der Laufzeitbibliothek der Programmiersprache zusammengeführt.
Eingebunden werden können auch Einheiten aus externen Bibliotheken.
Laden
Bei Einsatz eines Compilers erforderlich.
Die vom Verbinder erstellte Datei wird in den Hauptspeicher geladen.
Dies übernimmt entweder der Kommandointerpreter des jeweiligen Betriebssystems oder ein speziell zu aktivierendes Programm.
Ausführen
Ja nach verwendeter Technologie ist entweder selbständig lauffähiger Code entstanden oder die Ausführung läuft unter Kontrolle eines Interpreters.
Mitunter werden im Laufe des Ausführungsprozesses Einheiten nachgeladen. Dies spielt eine Rolle bei Überlagerungsstrukturen (overlays; bei modernen Rechnersystemen kaum noch erforderlich) oder (zunehmend) bei Nutzung von dynamischen Bibliotheken.
Wird direkt in Maschinensprache codiert, so ist das notierte Programm sofort auf dem Rechner ausführbar, dessen Maschinensprache verwendet wird. In allen anderen Fällen ist eine Übersetzung notwendig. Grundsätzlich werden folgende Typen von Übersetzern unterschieden: Assembler kommen für Sprachen der 2. Generation zum Einsatz, Interpreter und Compiler für Sprachen ab der 3. Generation.
Die Arbeit mit Compiler bzw. Interpreter unterscheidet sich in einigen wichtigen Arbeitsschritten:

Interpretieren                 Compilieren

    Editor                       Editor
       |                            |
+-------------+              +-------------+
|  Quelltext  |              |  Quelltext  |
+-------------+              +-------------+
       |                            |
       |                       Precompiler
       |                            |
       |                     +-------------+
       |                     | aufgelöster |
       |                     |  Quelltext  |
       |                     +-------------+
       |                            |         +---------+
       |                            |         |         |
  Interpreter                    Compiler     |    Bibliothekar
       |                            |         |         |
       |                     +-------------+  |  +-------------+
       |                     |  Objektcode |--+  |  Bibliothek |
       |                     +-------------+     +-------------+
       |                            |                   |
       |                            |-------------------+
       |                        Verbinder
       |                            |
+-------------+              +-------------+
|Maschinencode|              |Maschinencode|
+-------------+              +-------------+
       |                            |            +-------------+
   Programm-                    Programm-        |  Dyn. Link- |
   ausführung                   ausführung ------|  Bibliothek |
                                                 +-------------+
Der Interpreter ermöglicht - bei kleinen Problemen - einen schnelleren Testzyklus, der Weg über den Compiler führt zu weitaus effektiverem Maschinencode.
Der Assembler ist - in Bezug auf die genannten Arbeitsschritte - mit dem Compiler vergleichbar.
In den meisten Programmiersystemen wird mit einem Compiler gearbeitet. Manchmal stehen auch alternativ Compiler und Interpreter zur Verfügung (z.B. bei manchen BASIC-Systemen).

Möglich sind jedoch auch Zwischenstufen.
Ein Beispiel stellen sogenannte Compreter dar:

  1. Der Quelltext wird mit einem Compiler in einen Zwischencode übersetzt.
    Der Zwischencode wird auch als P-Code (Pseudo-Code; z.B. im Zusammenhang mit Pascal) oder Bytecode (im Zusammenhang mit Java) bezeichnet.
    Es handelt sich dabei um den "Maschinencode" eines abstrakten Rechners (einer virtuellen Maschine).
  2. Der Zwischencode wird auf einem realen Rechner mit Hilfe eines Interpreters ausgeführt.
    Es gibt die Tendenz, Code zu erzeugen, der zwischen verschiedenen Maschinen austauschbar ist. Der Code ist dann auf jeder Maschine ausführbar, über einen entsprechenden Interpreter verfügt.
Diese Technologie wurde von einigen frühen Pascal-Systemen (z.B. UCSD Pascal) genutzt (P-Code) und spielt gegenwärtig wieder im Zusammenhang mit Java eine wichtige Rolle (Java Virtual Machine).
P-Code ist im allgemeinen nicht zwischen verschiedenen Maschinen austauschbar, der bei Java übliche Bytecode ist es.

Für einige Sprachen ist eine Vorverarbeitung des Quelltextes durch Precompiler typisch: Makroanweisungen werden aufgelöst, eine bedingte Compilation wird möglich. Dies wird z.B. standardmäßig von C und C++ genutzt.
Bei anderen Sprachen (z.B. Pascal) sind Möglichkeiten zur Precompilierung abhängig vom jeweiligen Programmiersystem und liegen meist deutlich unter denen in C.

Mitunter erfolgt die Compilierung über den Zwischenschritt der Übersetzung in eine andere ("reale") Programmiersprache:

1. Stufe:
Übersetzung von der Quellsprache in eine Mittlersprache.
Dies kann sein
2. Stufe:
Übersetzung der Mittlersprache.
In Abhängigkeit von der internen Arbeitsweise des Compilers kann zwischen Ein- und Mehrpaßcompilern unterschieden werden.

Objektcode läßt sich kennzeichnen als (noch) nicht ausführbarer Maschinencode (binär codierte Maschinenbefehle):

Der Verbinder hat die Aufgabe, externen Referenzen aufzulösen, d.h. er fügt die benötigten Ressourcen zu einer Einheit zusammen. Die relativen Adressen werden dabei umgerechnet. Es entsteht ausführbarer Maschinencode.
Bei einigen Systemen ist es möglich, einige der benötigten Ressourcen erst zur Laufzeit anzufordern (dynamische Bibliotheken).

Typischerweise besitzen alle Programmeinheiten unterschiedliche relative Adressen.
Bei Speicherplatzmangel können unter Umständen sogenannte Überlagerungsstrukturen (overlays) aufgebaut werden (oft in DOS-Systemen verfügbar): Verschiedene Programmeinheiten besitzen dann die gleichen relativen Adressen, d.h. nur eine von ihnen ist jeweils im Hauptspeicher geladen.

Der Programmverbinder verarbeitet als Eingabe eine oder mehrere Objektcodedateien sowie Objektcodebibliotheken. Erforderliche Bibliotheken sind die Laufzeitbibliotheken des Sprachsystems und gegebenenfalls anwendungsbezogene private Biblotheken.
Die Laufzeitbibliotheken enthalten die sogenannten Systemprozeduren (Ein-/Ausgabeprozeduren, mathematische Standardfunktionen, usw.) der Programmiersprache.

Zur Ausführung wird das Programm in den Hauptspeicher geladen. Die relativen Adressen werden dabei durch absolute Adressen ersetzt, in dem das Programm eine Startadresse erhält. Je nach Betriebssystem ist diese Startadresse entweder bis zum Ende der Programmausführung fest (z.B. DOS) oder kann im Bedarfsfall verändert werden (z.B. Windows, UNIX).
Nichtaufgelöste externe Referenzen können unter bestimmten Voraussetzungen zur Laufzeit abgedeckt werden. Dies geschieht z.B. unter Windows mit Hilfe von sogenannten DLL's (Dynamic Link Library).

Pascal-Systeme arbeiten typischerweise mit einem Compiler. Das folgende Schema gibt für die Pascal-Systeme XLP (XL Pascal, Unix) und MSP (Microsoft Pascal, DOS) an, welche Programme und Dateien bei der Erstellung eines lauffähigen Programms eine Rolle spielen (können).

XLP                                                       MSP
---                                                       ---
             vi           Editor         edit
                            |
                     +-------------+
    pgm.pas          |  Quelltext  |             pgm.pas
                     +-------------+
                            |
             xlp         Compiler        pl
                            |
                     +-------------+
    pgm.o            |  Objektcode |--+          pgm.obj
                     +-------------+  |
                            |         |  lib
             ar             |     Bibliothekar
                            |         |
                            |   +-------------+
    ##.a                    |   |  Bibliothek |  ##.lib
                            |   +-------------+
                            |         |
            (ld)         Programmverbinder
                            |         |  (link)
                     +-------------+  |
    pgm              |Maschinencode|--+          pgm.exe
                     +-------------+
                            |            +-------------+
                        Programm         |  Dyn. Link- | ##.dll
                        ausführung ------|  Bibliothek |
                                         +-------------+
Tendenzen

Im Zusammenhang mit der zunehmenden Vernetzung der Rechentechnik in heterogenen Netzen gibt es Überlegungen, Code zu erzeugen, der über Netz ausgetauscht und dann ohne weitere Maßnahmen direkt auf der jeweiligen Maschine ausgeführt werden kann.
Der Code kann dann nicht direkt ausgeführt werden, sondern wird durch eine Ablaufumgebung interpretiert.
Auf jeder Maschine, die eine solche Ablaufumgebung existiert, kann der Code unverändert ausgeführt werden. Die notwendigen Anpassungen an das jeweilige System werden automatisch von der Ablaufumgebung übernommen.

Systeme, die gegenwärtig nach dieser Philosophie arbeiten, sind u.a. Hotjava (Sprache Java, C++ ähnlich) und Oberon/F (Oberon-2, Pascal-ähnlich).

Siehe auch:



P. Böhme, 29.08.1995