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.
Compiler führen folgende Schritte aus: Präprozessor -> Compiler -> Assembler -> Linker -> Output Converter (Hexfile) Assembler nur: (Präprozessor ->) Assembler -> Linker -> Output Converter (Hexfile) Peter
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
Peter, da hast du mir meine Frage vorweggenommen. Ich danke! Was macht denn der Linker? Wozu braucht es den? 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.
Ich glaube, ich habe es jetzt verstanden. Vielen Dank dafür! Gruß Jens
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
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.