Compilerbau Teil 1: Einführung Compiler und der ganze Rest

Die Seite wird erstellt Ilka Bader
 
WEITER LESEN
Compilerbau Teil 1: Einführung Compiler und der ganze Rest
Compilerbau

                                     Teil 1: Einführung
                                 Compiler und der ganze Rest

Comppilerbau – SS 2018 – Teil 1/Einführung                     05.04.18 1
Literatur und Web

      [1-1]         Wirth, Niklaus: Compilerbau. Teubner, 3. Auflage, 1984
      [1-2]         Maurer, Dieter: Übersetzerbau: Theorie, Konstruktion, Generierung.
                    Springer, 1992
      [1-3]         Doberkat, Ernst-Erich: Praktischer Übersetzerbau. Springer 1990
      [1-4]         https://de.wikipedia.org/wiki/Backus-Naur-Form
                    https://de.wikipedia.org/wiki/Erweiterte_Backus-Naur-Form
                    https://de.wikipedia.org/wiki/Angereicherte_Backus-Naur-Form
                    https://www.iso.org/standard/26153.html
                    https://en.wikipedia.org/wiki/Wirth_syntax_notation

      [1-5]         https://de.wikipedia.org/wiki/Syntax
                    https://de.wikipedia.org/wiki/Syntaxdiagramm
      [1-6]         https://de.wikipedia.org/wiki/Compiler

Comppilerbau – SS 2018 – Teil 1/Einführung                                               2
Übersetzungsprozess von C I – Überblick

                              Syntax Analyse (Parser)         Compiler
                                                                                 Ableitungsbaum

                                      Optimierung             Compiler

                                                                                 Ableitungsbaum

                                   Codegenerierung            Compiler
                                                                                 Sequenz Zwischensprache
                                                                                 Sequenz Assembler

                                      Assemblieren            Assembler
       Module als
                                                                                 Sequenz Tabellen
       Object-Files

                                   Zusammensetzen             Linker/Linkage Editor
       Object-File                                                               Sequenz Tabellen

                                             Laden            Lader/Loader
        Prozess-                                                                  Daten im RAM
        Image

                                                 Ausführung

Comppilerbau – SS 2018 – Teil 1/Einführung                                                                 3
Übersetzungsprozess von C II

                       C-Programm                 Beispiel.c
                                                               Preprozessor
                                                                                Include-Dateien
                       C-Programm mit
                       expandierten Makros        Beispiel.i
                                                               (Eigentlicher)
                                                               Übersetzer
                       Übersetztes Programm
                       ohne Bibliotheksroutinen   Beispiel.o
                                                               Binder           Hauptprogramm
                                                                                Bibliotheken
                       Fertiges ausführbares      Beispiel
                       Programm
                                                               Lader in Linux

                        Programm in
                        Ausführung

Comppilerbau – SS 2018 – Teil 1/Einführung                                                        4
Durchlauf (Pass)

              • Das Übersetzen erfolgt in mehreren Durchläufen (Pass), in denen
                das gesamte Programm vollständig gelesen und interpretiert
                wird.
              • Nach jedem Durchlauf wird das Programm in überarbeiteter
                Form neu in einer speziellen Datei angelegt; diese wird bei dem
                nächsten Durchlauf benutzt.
              • Die Steuerung der Durchläufe übernimmt gcc(I).
              • Bei Compilern sind 4 bis 5 Durchläufe üblich, es können auch
                erheblich mehr sein, z. B. PL/1 hatte bis zu 60 Durchläufe.

Comppilerbau – SS 2018 – Teil 1/Einführung                                        5
Übersetzungsprozess von C III – Syntaxanalyse

              1. Durchlauf: Makroexpansion
                 Es werden die Makrodefinitionen (C hat die Möglichkeit von Makros, in
                 Programmiersprachen ohne Makros wird dieser Schritt ausgelassen)
                 vermerkt und alle Makro-Aufrufe mit den Makrokörpern samt
                 Parametern ersetzt.

              2. Durchlauf: Syntaktische Prüfung
                 Entspricht der entstandene Text den Regeln der Sprache? Z.B. Hat jede
                 öffnende Klammer (rund oder geschweift) eine korrespondierende
                 schließende? Wird jedes Statement durch ein Semikolon
                 abgeschlossen?

              3. Durchlauf: Semantische Prüfung
                 Sind alle Variablen und Funktionen deklariert? Werden sie
                 übereinstimmend damit benutzt?

Comppilerbau – SS 2018 – Teil 1/Einführung                                               6
Übersetzungsprozess von C IV

              4. Durchlauf: Optimierung (optional)
                 Können Deklarationen weggelassen werden, da die Variablen
                 nicht benutzt werden? Lassen sich Schleifen verkürzen?

              5. Durchlauf: Erzeugung von Assembler-Code
                 Für jedes Statement wird der entsprechende Assemblercode
                 generiert, so dass das generierte Programm das tut, was es laut
                 Sprachdefinition tun sollte.

              6. Durchlauf: Assemblieren
                 Der Compiler ist jetzt fertig; es wird ein Assembler gestartet, der
                 das generierte Assembler-Programm in eine Objektdatei
                 übersetzt.

Comppilerbau – SS 2018 – Teil 1/Einführung                                             7
Übersetzungsprozess von C V

              • Die generierte Objektdatei ist aus folgenden Gründen nicht
                ausführbar:
                 – Es fehlen aufgerufene und nicht programmierte Routinen, z.
                   B. System.out.println() in Java oder printf() in C.
                 – Globale Variablen haben noch keine feste Position (Adresse),
                   sie könnten an verschiedenen Stellen angelegt werden.

              • Der Binder (Linker, Linkage Editor) setzt das endgültige
                Programm unter Verwendung von Bibliotheken zusammen und
                positioniert die globalen Variablen. Erst dessen Ergebnis kann
                ausgeführt werden.

Comppilerbau – SS 2018 – Teil 1/Einführung                                        8
Übersetzungsprozess von C V

              7. Durchlauf: Binden
                 Der Binder durchsucht Objektbibliotheken, um ein
                 unvollständiges Programm mit den nicht selbst programmierten,
                 aber aufgerufenen Subroutinen zu ergänzen.
                 Am Ende ist eine direkt ausführbare Datei entstanden.

            Jetzt erst kann die Datei mit Maschinencode vom Betriebssystem
            in den RAM geladen und ausgeführt werden.

            Java wird etwas anders realisiert: es wird nicht bis zum
            Maschinencode übersetzt, sondern in eine Zwischensprache: Java-Byte-Code.
            Dieser wird in einem Interpreter (Virtuelle Maschine) ausgeführt.
            Bei Linux ist es meistens auch etwas anders.

Comppilerbau – SS 2018 – Teil 1/Einführung                                              9
Assembler I

              • Assembler = Übersetzer für Programme in einer symbolischen
                Maschinensprache
              • Die Sprache Assembler ist für jeden CPU-Typ anders und spiegelt
                die Eigenarten der CPU-Architektur wieder.
              • Zur Assembler-Sprache gehören u.a.:
                 – Befehle (Instruktionen) der CPU.
                 – Makros als Zusammenfassungen mehrerer Befehle.
                 – Anweisungen zur Reservierung von Speicherplatz.
                 – Anweisungen zur Belegung von Speicherplatz.
              • Der Assembler übersetzt das Assembler-Programm in ein
                maschinen-codiertes Format, dem Objektformat.
              • Diese Dateien heißen daher Objektdateien.

Comppilerbau – SS 2018 – Teil 1/Einführung                                        10
Assembler II – Fiktives Beispiel

      Assembler                              Objekt-Datei

Comppilerbau – SS 2018 – Teil 1/Einführung                  11
Assembler III

              • Assemblersprachen sind in der Regel spalten-orientiert, d.h. die
                Zeilen haben ein festes Format, das einzuhalten ist.
              • Ein wichtiges Charakteristikum eines Assemblers ist, dass die
                Assembler-Befehle fast immer 1:1 zu Maschinenbefehlen umgesetzt
                werden (Ausnahme: Verwendung von Makros).
              • Sprungmarken = Label = Namen für Speicherstellen (symbolische
                Adressen) von bestimmten Instruktionen, z. B. Beginn einer
                Subroutine

              • Das Programmieren in Assembler ist sehr mühselig, da:
                 – es viel Zeit kostet,
                 – viele Fehler gemacht werden können.
                Aber: In Assembler sind die effizientesten Programme realisierbar

Comppilerbau – SS 2018 – Teil 1/Einführung                                          12
Compiler vs. Assembler

              • Höhere Programmiersprachen, wie z. B. C oder Java, werden
                durch Compiler in Maschinensprache übersetzt.
              • Compiler = Übersetzer für Programme in einer höheren
                Programmiersprache, die sich dadurch auszeichnet, dass ein
                Statement ("Befehl") dieser Sprache in mehrere Befehle in der
                Maschinensprache übersetzt werden muss.

Comppilerbau – SS 2018 – Teil 1/Einführung                                      13
Aufbau von Befehlen

Comppilerbau – SS 2018 – Teil 1/Einführung   14
Beispiel: Objekt-Fileformat (a.out) I

Comppilerbau – SS 2018 – Teil 1/Einführung   15
Beispiel: Objekt-Fileformat (a.out) II

              • Header = Deskriptor für den Aufbau der Datei
              • Text = Tabelle mit dem übersetzten Code
              • Data = Tabelle mit den vorbelegten globalen Daten (static)
              • Relocation Information = Verschiebungsinformation = Tabelle
                mit der Beschreibung der Stellen im Code, die durch den Linker
                korrigiert werden müssen
              • Symbol-Tabelle = Tabelle mit den Deskriptoren von Symbolen,
                z.B. Namen von Variablen oder Routinen
              • String-Tabelle = Feld mit de Zeichenketten (Strings), die die
                Symbole ausmachen
                Da dieselben Symbole mehrfach vorkommen können, werden die
                Strings in der String-Tabelle und die Verweise darauf in der
                Symbol-Tabelle abgelegt.

Comppilerbau – SS 2018 – Teil 1/Einführung                                       16
Verschiebungsinformation (Relocation Info)

         • Wenn ein Modul auf eine static-Variable zugreift, dann muss der Ort,
           also dessen Adresse zum Zeitpunkt des Bindens berechnet werden,
           denn der Ort hängt von der Position des betreffenden Moduls
           innerhalb der Binärdatei ab.
         • In der Tabelle Relocation Information stehen Deskriptoren, die
           festlegen, an welchen Stellen im Code die zu korrigierende Adressen
           stehen.
         • Wenn die CPU mit einer relativen Adressierungsart darauf zugreift, ist
           die Korrektur zwingend erforderlich.

         • Wenn die CPU relativ zu einem Register, z.B. PC, darauf zugreift, so
           steht im Code lediglich die Differenz der Adressen zwischen Register
           und dem Ort. Dann ist eine Verschiebung nicht nötig.
         • Dasselbe gilt analog für Zugriffe auf absolute Adressen.

Comppilerbau – SS 2018 – Teil 1/Einführung                                          17
Bemerkungen

              • Die beiden vorgestellten Formate sind nur Beispiele.
              • Für Objekt-Dateien gibt es unter Linux folgende Formate:
                 – Klassisches a.out-Format (siehe oben, veraltet)
                 – COFF (Common Object File Format), veraltet
                   Siehe z.B. http://de.wikipedia.org/wiki/COFF
                 – ELF (Executable and Linking Format)
                   Siehe z.B.
                      http://de.wikipedia.org/wiki/
                      Executable_and_Linking_Format
                      http://www.linux-kernel.de/appendix/ap05.pdf

                   Heutige Systeme benutzen nur noch das ELF-Format.

Comppilerbau – SS 2018 – Teil 1/Einführung                                 18
Binden I

Comppilerbau – SS 2018 – Teil 1/Einführung   19
Binden II - Binärcode (Objectcode)

Comppilerbau – SS 2018 – Teil 1/Einführung   20
Binden III - Bibliotheken

Comppilerbau – SS 2018 – Teil 1/Einführung   21
Begriffe

              • Bibliothek = Archiv = Library = Datei mit mehreren benannten
                Informationsblöcken einschließlich eines Verzeichnisses; jeder Block
                kann eine eigenständige Datei aufnehmen, z. B. Zip-Archive
              • Beispielstruktur:
                             Number

                                                     Datei   Datei
                                                                     ...   Datei
                             Magic

                                      Header Index
                                                       1       2             N

              • Objektbibliothek = Bibliothek für Objektdateien
              • Binärprogramm = Aus vielen Objektdateien bzw. Bibliotheken
                zusammengesetztes ausführbares Programm

Comppilerbau – SS 2018 – Teil 1/Einführung                                             22
Beispiel: Bibliothek (ar-Format)

                                             Siehe http://sourceware.org/binutils/docs/binutils/ranlib.html
Comppilerbau – SS 2018 – Teil 1/Einführung                                                                    23
Binden IV

Comppilerbau – SS 2018 – Teil 1/Einführung   24
Binden V

       •     Jede übersetzte, ungebundene Objekt-Datei wird Modul genannt.
       •     Der Linker arbeitet pro Modul in folgenden Schritten:
              1. Kopieren des aktuellen Moduls ans Ende der bisherigen
              2. Feststellen, was dieses neue Modul an Symbole definiert
              3. Diese aus der Tabelle der Unbekannten entfernen und in die
                 Tabelle der Bekannten eintragen
              4. Alle Verweise (Aufrufe etc.) im bisher geladenen Teil mit dem
                 neuen Modul verbinden
              5. Alle Verweise auf noch nicht geladene Routinen bzw. in Tabelle der
                 Unbekannten bringen.
              6. Ist die Tabelle der Unbekannten leer, so terminiert das Laden,
                 ansonsten werden die Bibliotheken nach der Definition der
                 Unbekannten durchsucht; wird ein Modul dazu gefunden, geht es
                 mit Schritt 1 weiter, ansonsten wird eine Fehlermeldung
                 produziert.

Comppilerbau – SS 2018 – Teil 1/Einführung                                            25
Zeitpunkte des Bindens

              • Direkt während der Übersetzung des Programm
                Dadurch entsteht eine ausführbare Datei mit allen Teilen.
              • Erst zum Zeitpunkt des Ladens in den RAM
                Es entstehen kleine nicht-ausführbare Programme, die während
                des Startens mit aktuellen Versionen der fehlenden Teile
                verbunden werden.
                    – Der Linker ist dann Teil des Laders.
                    – Dies wird meist bei Linux gemacht.
              • Während der Laufzeit des Programms
                Der Binder läuft parallel zum Programm und verbindet nur die
                Routinen, die aufgerufen werden.

Comppilerbau – SS 2018 – Teil 1/Einführung                                     26
Hauptprogramm

              • C kennt keine Hauptprogramme, alle Routinen sind gleichwertige
                Funktionen, die Werte liefern (und deshalb einen Aufrufer
                benötigen).
              • Es wird ein in Assembler geschriebenes Hauptprogramm dazu
                gebunden, das eine C-Routine Namens "main" aufruft, so dass
                main() wie ein Hauptprogramm erscheint.

                  Pseudocode des Hauptprogramms

                  Initialize Register
                  Initialize Stack
                  Push(Parameter)
                  call _main(argc,arv,env) /* Haupt-Programm */
                  call _exit(0)            /* für return in main() */

Comppilerbau – SS 2018 – Teil 1/Einführung                                       27
Nach dieser Anstrengung etwas Entspannung...

                                                   Da liegt
                                                   noch ein
                                                   steiniger
                                                   Weg vor
                                                   uns...
Comppilerbau – SS 2018 – Teil 1/Einführung                     28
Sie können auch lesen