Hallo Leute,
mal eine grundlegende Frage:
Ein Compiler nimmt sich ja den Hochsprachen-Code und produziert dann
fürs Target-Device den Hex-Code. Was macht er als Zwischenschritt?
So wie ich das verstanden habe, wird der quasi-allgemeine z.B. C-Code
erst einmal in Assembler-Mnemonics übersetzt, und dann werden die
Assembler-Mnemonics in "Einsen und Nullen" (Maschinensprache) für das
Hex-File umgewandelt.
Was macht ein Assembler? Macht der nicht das gleiche (d.h.
Hochsprachen-Code in Assembler-Mnemonics übersetzen), bis auf den
letzten "in-Einsen-und-Nullen-Umwandel-Schritt"?
Denn wenn ich direkt Assembler-Mnemonic-Code schreibe, brauche ich dann
auch noch einen Compiler? Nach meinem Verständnis bräuchte ich ja dann
nur den letzten Teil des Compilers, der aus den Mnemonics den
Maschinencode erzeugt.
Ich würde einfach gerne mal von den Definitionen klarkriegen, was was
ist ;-)
Danke schon mal für eure Hilfe.
Gruß
Jens
Jens schrieb:> Was macht ein Assembler? Macht der nicht das gleiche (d.h.> Hochsprachen-Code in Assembler-Mnemonics übersetzen), bis auf den> letzten "in-Einsen-und-Nullen-Umwandel-Schritt"?
Noe. Du hast das Programm ja schon in Assembler-Mnemonics geschrieben.
Beim Assembler wird jeder Befehl wie er geschrieben ist auch so ins
binaere uebersetzt. Bei einer Hochsprache koennen aus einem
Hochsprachenbefehl mehrere Assemblerbefehle entstehen.
Nimm z.B. eine einfache Berechnung C = A * B;
Wenn der Compiler so etwas liest muss er da eine ganze Latte von
Assemblerbefehlen draus erzeugen. Je nach dem ob die Variabeln Integer
oder Fliesskomma werte darstellen oder ob die CPU ueberhaupt
Multiplikationen kann.
Auch kann so ein Hochsprachenprogramm fuer unterschiedlichste CPUs
uebersetzt werden. Ein Assemblerprogramm ist dafuer nur fuer eine
bestimmte CPU geschrieben worden.
Helmut Lenzen schrieb:> Jens schrieb:>> Was macht ein Assembler? Macht der nicht das gleiche (d.h.>> Hochsprachen-Code in Assembler-Mnemonics übersetzen), bis auf den>> letzten "in-Einsen-und-Nullen-Umwandel-Schritt"?>> Noe. [...]
Ich glaube du hast die Frage missverstanden: Ich meinte, wenn ich einen
Code in C schreibe, kann ich dann einen Assembler darauf loswerfen, der
mir Assembler-Code ausspuckt? Anders ausgedrückt: Was "frisst" ein
Assembler? ;-)
Gruß
Jens
Ein Assembler macht genau das, was Du hinschreibst, nicht mehr und nicht
weniger.
Ein Compiler übersetzt Hochsprachenelemente in Assembler. Dabei darf er
optimieren. Er macht also nur funktionell das, was Du hinschreibst.
Außerdem übernimmt er viele lästige Verwaltungsaufgaben (Stack,
Variablen) und Grundrechenarten (automatisches Hinzufügen einer
Library).
Peter
Man könnte es eventuell auch so ausdrücken.
Ein Compiler übersetzt ein in einer Hochsprache formuliertes Programm in
Assemblercode. Ein nachgeschalteter Assembler übersetzt dieses dann auf
echten Maschinencode (also in die Hex-Zahlen). Wenn du Assembler
programmierst, dann setzt du dein Programm in dieser Kette einfach
später auf. Der Schritt von der konzeptionellen Ideen zur tatsächlichen
Realisierung ist in Assembler für den Programmierer größer als mit einer
Hochsprache, weil sich hier der Programmierer um viele Details kümmern
muss, die ihm sonst der Compiler abnimmt. Dafür sind die Freiheiten
allerdings auch größer, weil ein Compiler nun mal auch nichts anderes
als eine Maschine ist, die nach einem fixen Schema vorgeht.
Jens schrieb:> Ich meinte, wenn ich einen> Code in C schreibe, kann ich dann einen Assembler darauf loswerfen, der> mir Assembler-Code ausspuckt? Anders ausgedrückt: Was "frisst" ein> Assembler? ;-)
Für ein Hochsprache, z.B. C, brauchst Du einen Compiler, den Assembler
braucht Du genau dann und nur dann, wenn Du auch in Assembler schreibst.
Gruß Dietrich
Jens schrieb:> Ich glaube du hast die Frage missverstanden: Ich meinte, wenn ich einen> Code in C schreibe, kann ich dann einen Assembler darauf loswerfen, der> mir Assembler-Code ausspuckt? Anders ausgedrückt: Was "frisst" ein> Assembler? ;-)
Wenn du dem Assembler C-Code vorwirfst wird er ihn wieder ausspucken.
Ein Assembler braucht einen Assembler Quelltext.
Die meisten C-Compiler koennen zwar als Zwischenschritt dir
Assemblercode generieren das ist dann wieder ein Assembler Quelltext und
daraus dir dann deine Binaries machen im allgemeinen kann der Compiler
aber auch direkt dir deine Binaries erzeugen.
Hallo,
danke für die zahlreichen Antworten, mir ist schon Einiges klarer
geworden.
(Hochsprache ->) Assembler-Mnemonics -> Hex-File
Der erste Schritt ist also (bei festem Target) optional.
Aber eine Frage ist noch nicht ganz geklärt:
Der Schritt von den Assembler-Mnemonics, also unserem lieben
Assembler-Code, den wir tagtäglich in unsere Tastaturen hacken, zu dem
Hex-File, das wir dann in den Controller übertragen, von wem wird der
übernommen? Es geht also um den zweiten Schritt in obigem Diagramm.
Gruß
Jens
Jens schrieb:> Der Schritt von den Assembler-Mnemonics, also unserem lieben> Assembler-Code, den wir tagtäglich in unsere Tastaturen hacken, zu dem> Hex-File, das wir dann in den Controller übertragen, von wem wird der> übernommen? Es geht also um den zweiten Schritt in obigem Diagramm.
Vom Assembler.
Das kann ein eigenständiger Assembler sein oder ein Teil eines
COmpilers, der aber prinzipiell die gleiche Aufgabe erfüllt.
Jens schrieb:> Peter, da hast du mir meine Frage vorweggenommen. Ich danke!>> Was macht denn der Linker? Wozu braucht es den?
Um mehrere Teile, die unabhängig voneinander compiliert werden,
miteinander zu verbinden - sie zusammen-zu-"linken"
to link == verbinden
Ein C-Programm welches aus 2 Millionen Lines of Code besteht, hat man
nicht in einem einzigen C-File, sondern teilt es in funktionale Gruppen
in verschiedene Files auf. Es ist der Job des Linkers, diese Einzelteile
nach dem getrennten Compilieren zu einem Ganzen zu verbinden.
Ausserdem geht ein COmpiler immer davon aus, dass er auf einen Satz von
Standardfunktionen zurückgreifen kann. Die implementiert nicht der
Compiler, sondern er hinterlässt für den Linker die Information, dass er
diese und jene Information bzw. Standardfunktion aus diversen
Bibliotheken (am prominentesten: die Runtime-Bibliothek) hinzufügen
soll.
Folgende C Zeile
c = a + b;
wird durch den Compiler in folgendem Assemblercode uebersetzt
89 81 ldd r24, Y+1 ; 0x01
9a 81 ldd r25, Y+2 ; 0x02
2b 81 ldd r18, Y+3 ; 0x03
3c 81 ldd r19, Y+4 ; 0x04
82 0f add r24, r18
93 1f adc r25, r19
9e 83 std Y+6, r25 ; 0x06
8d 83 std Y+5, r24 ; 0x05
Der Assembler macht dann die Hex-Code ganz links daraus.
Jens schrieb:> Was macht denn der Linker? Wozu braucht es den?
Bei groesseren Programmen ist es ueblich sie in kleinere Einheiten
aufzuteilen. Die werden dann getrennt compiliert und assembliert.
Aus den nun vorliegenden Einzeilteilen und aus vorgefertigten Teilen aus
einer Bibliothek baut der Linker dann das komplette Programm zusammen.
to link = verbinden.
Danke, ich fühle mich richtig erleuchtet.
Peter Dannegger schrieb:> Assembler -> Linker -> Output Converter (Hexfile)
Also fügt der Linker in den Maschinencode, den der Assembler ausspuckt,
noch etwas ein? Das finde ich seltsam, ich hätte es vorher erwartet.
Was genau ist dann der Output-Converter, wenn der Assembler schon den
fertigen Maschinencode ausspuckt?
Gruß
Jens
Jens schrieb:> Danke, ich fühle mich richtig erleuchtet.>> Peter Dannegger schrieb:>> Assembler -> Linker -> Output Converter (Hexfile)>> Also fügt der Linker in den Maschinencode, den der Assembler ausspuckt,> noch etwas ein? Das finde ich seltsam, ich hätte es vorher erwartet.
Wäre prinzipiell auch möglich.
Aber anders rum ist es universeller.
Wenn der Linker auf Assembler Code Ebene arbeitet, muss der Assembler ja
wieder alles übersetzen. Und genau das wollen wir ja nicht. Der Linker
mnuss von Assembler Code bzw. überhaupt von Code nix wissen. Der
COmpiler bzw. Assembler hat ihm nur die Information hinterlassen: hier
und hier setzt du die Startsdresse der Funktion xyz bzw. die Adresse der
gloablen Variablen abc ein. Mehr muss der Linker nicht können.
>> Was genau ist dann der Output-Converter, wenn der Assembler schon den> fertigen Maschinencode ausspuckt?
Na ja. Irgendwer muss ja das ganze Machwerk ja zb auch in ein File
schreiben. Garniert mit Informationen, die zb ein Brennprogramm benutzt
um den Code am endgültigen µC an die richtige Stelle im Speicher zu
bugsieren. Und dann gibt es da ja auch noch unterschiedliche Fileformate
etc. etc. usw.
Jens schrieb:> Also fügt der Linker in den Maschinencode, den der Assembler ausspuckt,> noch etwas ein? Das finde ich seltsam, ich hätte es vorher erwartet.>
Teilweise macht er das. In erster Linie aber Bibliotheksfunktionen wie
z.B.
Fliesskomma , Stringverarbeitungs etc.
> Was genau ist dann der Output-Converter, wenn der Assembler schon den> fertigen Maschinencode ausspuckt?
Normalerweise liefert der Linker ein Binaerfile. Der Outputconverter
macht daraus dann Intel-Hex , Motorola S19 etc.
Jens schrieb:> Ein Compiler nimmt sich ja den Hochsprachen-Code und produziert dann> fürs Target-Device den Hex-Code. Was macht er als Zwischenschritt?
Einen Parse-Tree aufbauen.
Diesen traversieren und passenden Code ausgeben - das kann direkt
Maschinencode sein, oder Assembler, oder ein Zwischencode.
Hallo,
es gab zwar Compiler, die Assembler-Mnemonics erzeugen, und manchen kann
man das auch heute noch für Analysen befehlen, aber technisch ist dieser
Schritt überflüssig - genausogut kann der Compiler Binärcode für den
Linker erzeugen. Das mit dem Assembler geistert bloss noch durch
Lehrbücher und Seminare, oder es ist einfach ein Missverständnis: unter
Assembler werden nämlich 3 verschiedene Dinge verstanden. Erstens die
Assembler-Mnemonics, die man (halbwegs) lesen kann. Zweitens das
Programm, das aus diesen Mnemonics den Binärcode erzeugt, den kein
normaler Mensch lesen kann. Und drittens, meiner Ansicht nach nicht
korrekt, diesen Binärcode, der ja den Mnemonics 1:1 entspricht, von
Feinheiten wie Präfixe u.Ä. mal abgesehen. Den sollte man nicht als
Assembler bezeichnen, weil man ja sonst zwischen den Mnemonic-Dateien
und dem Ergebnis ihrer Übersetzung, dem Maschinencode, nicht
unterscheiden kann.
Der Vollständigkeit halber: der erzeugte Binärcode ist noch nicht fertig
und auch nicht durch den Prozessor ausführbar: die Adressen sind nur
vorläufig und erhalten erst durch den Linker ihren endgültigen Wert, da
erst dieser den Überblick über das gesamte Programm hat.
Ein Programm entsteht heute aus Modulen, die in einer Hochsprache, auch
in verschiedenen, oder in Assembler geschrieben werden, z.B. .C, .CPP
und .ASM Dateien. Compiler oder Assembler erzeugen daraus relozierbare
Binärdateien, z.B. .REL oder .OBJ, die der Linker zum fertigen Programm
zusammensetzt wie etwa .EXE.
Gruss Reinhard