Hallo Siro,
Je nach Compilertechnologie ist das aber so.
Die alten Compiler verwendeten im Prinzip einfach Macros.
Damit die Macros zusammen passen, braucht es eine Konvention, z.B. dass der Parameter in B steht und das Resultat des Macros auch in Register B übergeben wird.
Jetzt kann aber die CPU mit Reg B nicht rechnen.
Das Macro für i++; sieht dann so aus:
Das nächste Macro beginnt dann wieder mitCode:MOV B, A INC A MOV A, B
Das Andere ist dann, ab welchem Punkt man nicht mehr inline Code erzeugt, sondern Funktionen in einer Laufzeitbibliothek aufruft.Code:MOV B, A ....
Beide Verfahren vereinfachen den Compiler ganz enorm, ergeben aber nicht sehr effizienten Code.
Diese Compiler funktionieren eigentlich wie Interpreter, es wird einfach Statement für Statement in Code übersetzt.
Moderne Compiler erzeugen nach der Lexikalischen und Syntaktischen Analyse einen Baum in einem Pseudocode.
Dieser Baum wird dann auf logischer Ebene analysiert und optimiert. Hier kann man unwirksamen Code entfernen, Speicherzugriffe auf Variablen optimieren und Schleifen optimieren.
Dann erst wird Maschinencode erzeugt und die Registernutzung optimiert.
Solche Compiler sind natürlich etwas aufwendiger.
Neben dem besseren Code bringt das ganze noch einen weiteren Vorteil:
Der Compiler besteht aus 3 Teilen, dem Frontend, dieses ist Sprachspezifisch und erzeugt den Baum, der Optimierer, welcher Sprachunabhängig ist und dem Backend oder Codegenerator, welches CPU-Spezifisch aber Sprachunabhängig ist.
Für unterschiedliche Sprachen muss man dann nur das Frontend neu entwickeln und für eine spezielle CPU nur ein neues Backend.
MfG Peter(TOO)
Lesezeichen