|
1 | 1 | \lesson{Preprocessing, Compiler, Assembler, Linker} |
2 | 2 |
|
3 | | -In der letzten Lektion klang es bereits an -- was der Befehl \texttt{g++} |
4 | | -eigentlich tut, ist mehr, als nur Kompilieren im strengen Sinne des Wortes. Wir |
5 | | -wollen jetzt kurz erkunden, welche anderen Schritte in den Prozess vom |
6 | | -Quellcode in die ausführbare Datei notwendig sind und wie sie geschehen. Das |
7 | | -ist im Alltag nicht sehr wichtig, kann uns aber helfen, einige Fehlermeldungen |
8 | | -besser zu verstehen. Von daher müsst ihr auch nicht alles hier beschriebene |
9 | | -vollständig verstehen. |
| 3 | +In der letzten Lektion habt ihr bereits das erste mal ein Programm kompiliert, |
| 4 | +d.h. ihr habt eine für Menschen lesbare Datei in eine für Computer lesbare Datei |
| 5 | +übersetzt. Jetzt wollen wir uns etwas genauer anschauen was dabei eigentlich passiert. |
| 6 | +Ihr müsst dabei jetzt nicht jedes Detail vestehen, aber es ist praktisch zu |
| 7 | +wissen, wie der Compile Vorgang funktioniert um manche Fehlermeldungen zu verstehen. |
10 | 8 |
|
11 | 9 | In Lektion 1 haben wir vereinfacht dargestellt, dass der Compiler eine |
12 | 10 | Quelltextdatei mit der Endung \texttt{.cpp} nimmt und daraus direkt eine |
13 | 11 | ausführbare Datei erstellt. Die Schritte, die hier eigentlich in einem Befehl |
14 | 12 | durchgeführt werden, aber zu trennen sind, sind das \emph{Preprocessing}, das \emph{Kompilieren}, das |
15 | 13 | \emph{Assemblieren} und das \emph{Linken}. |
16 | 14 |
|
17 | | -Beim Preprocessing werden alle \texttt{\#include}-Anweisungen aufgelöst und so etwas wie Makros ersetzt. Das ist der erste Schritt, der passiert, wenn wir \texttt{g++} aufrufen. Das Ergebnis des Preprocessings ist ein \Cpp-Programm, das nur noch die \Cpp-Features enthält, die wir auch wirklich benutzen. Das ist der Grund, warum wir in den bisherigen Lektionen immer \texttt{g++ -o helloworld helloworld.cpp} benutzt haben, obwohl wir in \texttt{helloworld.cpp} auch \texttt{\#include <iostream>} stehen haben -- der Compiler hat das schon für uns erledigt. |
| 15 | +Beim Preprocessing werden alle \texttt{\#include}-Anweisungen aufgelöst. |
| 16 | +Das ist der erste Schritt, der passiert, wenn wir \texttt{g++} |
| 17 | +aufrufen. Das Ergebnis des Preprocessings ist ein erweitertes\Cpp-Programm, das nur noch die |
| 18 | +\Cpp-Features enthält, die wir auch wirklich benutzen. Das ist der Grund, warum wir |
| 19 | +in den bisherigen Lektionen immer \texttt{g++ -o helloworld helloworld.cpp} benutzt haben, |
| 20 | +obwohl wir in \texttt{helloworld.cpp} auch \texttt{\#include <iostream>} stehen haben |
| 21 | +-- der Compiler hat das schon für uns erledigt. |
18 | 22 |
|
19 | | -Das Kompilieren übersetzt unseren \Cpp-Code in eine Zwischenform, so genannten |
| 23 | +Das Kompilieren übersetzt unseren erweiterten \Cpp-Code in eine Zwischenform, so genannten |
20 | 24 | \emph{Assembler}. In Lektion 1 haben wir den Maschinencode angesprochen, in der |
21 | 25 | Befehle und Parameter an Befehle in 1en und 0en dargestellt werden. Assembler |
22 | 26 | ist quasi die nächst höhere Evolutionsstufe -- statt die Befehle binär zu |
|
52 | 56 | Objectfiles eine \texttt{main}-Funktion existiert, wird diese als |
53 | 57 | Eintrittspunkt für das Programm genommen, sonst gibt es einen |
54 | 58 | \emph{Linkerfehler}. Ein Linkerfehler tritt auch auf, wenn wir versuchen, eine |
55 | | -Funktion zu verwenden, die es nicht gibt (z.B. indem wir sie mittels |
56 | | -\texttt{extern} deklarieren, ohne später das relevante Objectfile mit |
57 | | -anzugeben). Linkerfehler deuten also darauf hin, dass wir vergessen haben, alle |
| 59 | +Funktion zu verwenden, die es nicht gibt (z.B. indem wir Funktionen aus einem |
| 60 | +Headerfile benutzen ohne das Header-File mit \texttt{#include} auch tatsächlich einzubinden). |
| 61 | +Linkerfehler deuten also darauf hin, dass wir vergessen haben, alle |
58 | 62 | relevanten Dateien auf der Kommandozeile anzugeben, oder dass eine |
59 | 63 | \texttt{main}-Funktion fehlt, oder dass wir in mehren Dateien eine Funktion |
60 | 64 | gleichen Namens haben, oder\dots |
61 | 65 |
|
62 | | -Um das Diagramm aus der ersten Lektion zu ergänzen, dies ist der Weg, den euer |
63 | | -Programm durch die verschiedenen Phasen geht: |
| 66 | +Wenn ihr das Programm aus der letzten Lektion kompiliert passiert im Prinzip also |
| 67 | +folgendes: |
64 | 68 |
|
65 | 69 | \begin{tikzpicture} |
66 | 70 | \tikzstyle{block} = [ shape=rectangle, rounded corners = 0.1cm, draw=black, inner xsep=0.5cm, inner ysep = 0.3cm ]; |
|
84 | 88 | unserer input-Datei zu der gewünschten zu kommen automatisch aus, wenn wir also |
85 | 89 | \texttt{g++ -o helloworld helloworld.cpp} eingeben, dann weiß der Compiler, |
86 | 90 | dass wir eine ausführbare Datei wünschen (da wir weder \texttt{-c} noch |
87 | | -\texttt{-S} angegeben haben) und dass er dafür kompilieren, assemblieren und |
88 | | -linken muss (da wir ihm eine \texttt{.cpp} Datei gegeben haben). Genauso konnte |
89 | | -er in der vorigen Lektion raten, dass \texttt{g++ -o tictactoe tictactoe.cpp |
90 | | - tictactoe.o} heißt, dass wir eine ausführbare Datei wollen, die aus einem |
91 | | -kompilierten und assemblierten \texttt{tictactoe.cpp} zusammen gelinkt mit |
92 | | -\texttt{tictactoe.o} bestehen soll. |
93 | | - |
| 91 | +\texttt{-S} angegeben haben) und dass er dafür preprocessen, kompilieren, assemblieren und |
| 92 | +linken muss (da wir ihm eine \texttt{.cpp} Datei gegeben haben). |
94 | 93 | \begin{praxis} |
95 | 94 | \begin{enumerate} |
96 | 95 | \item \texttt{assemble.cpp} enthält ein kleines (ziemlich nutzloses) |
|
119 | 118 | \end{enumerate} |
120 | 119 |
|
121 | 120 | \inputcpp{assemble.cpp} |
122 | | -\end{praxis} |
| 121 | +\end{praxis} |
0 commit comments