Guten Morgen liebe Gemeinschaft, ich bin ein blutiger Einsteiger in Sachen uC Programmierung, habe aber dennoch gute Erfahrungen in Sachen Programmierung bzw. das Verständnis dahinter. Ich lese mich seit ca. 4 Wochen quer durch sämtliche Artikel und Tutorials und habe schon recht gute Fortschritte gemacht. Momentan beschäftige ich mich mit dem Verständnis der Funktions- und Arbeitsweise des Compilers. Soweit so gut auch alles einfach zu verstehen. Nur eine Sache ist mir bisher schleierhaft und ich habe auch noch keine wirklich zufriedenstellende Antwort gefunden: Die AVR-Testprogramme die ich bisher geschrieben habe spielten sich immer in einer einzigen .c-Datei ab. (Ebenfalls soweit so gut) Nun las ich das der Linker beim Kompillieren mehrere .c-Dateien zu einem Programm zusammenfügt. Wie genau sieht dies denn aus? Kann ich mir das so vorstellen, dass die verschiedenen Quelltextdateien zu einer einzigen zusammengefügt, heißt die Quelltexte praktisch hintereinander geschrieben werden? Oder werden wirklich mehrere Dateien auf den uC geflasht und vom Linker verlinkt? Ich hoffe ich konnte euch mein Defizit erklären. Bin dankbar für jede brauchbare Antwort ;-) Gruß
:
Bearbeitet durch User
Christian O. schrieb: > Momentan beschäftige ich mich mit dem Verständnis der Funktions- und > Arbeitsweise des Compilers. > > Soweit so gut auch alles einfach zu verstehen. Nur eine Sache ist mir > bisher schleierhaft und ich habe auch noch keine wirklich > zufriedenstellende Antwort gefunden: > > Die AVR-Testprogramme die ich bisher geschrieben habe spielten sich > immer in einer einzigen .c-Datei ab. (Ebenfalls soweit so gut) > > Nun las ich das der Linker beim Kompillieren mehrere .c-Dateien zu einem > Programm zusammenfügt. > Wie genau sieht dies denn aus? Jede C-Datei wird einzeln und für sich compiliert. Das Ergebnis davon ist ein Object-File für jede C-Datei. Ein Object-File enthält bereits Maschinencode, so wie er vom Prozessor ausgeführt werden kann. Aber: da fehlt ja noch einiges. Zum einen müssen die Aufruf-Querverweise für die einzelnen Funktionen hergestellt werden, zum anderen hast du ja nicht alle Funktionen selber geschrieben. Da sind zb Hilfsfunktionen, die arithmetische Operationen durchführen (zb Multiplikation, zb Division), oder auch Standard-C Funktionen wie zb Stringverarbeitung oder sprintf oder ... Alle diese Funktionen wurden mal von jemandem geschrieben und vorübersetzt. Diese Einzelteile sind gesammelt worden und in einer Library verpackt worden. Und jetzt kommt der Linker ins Spiel. Er kriegt die einzelnen übersetzten Object-Files vorgesetzt, nimmt noch die System-Library dazu und versucht das jetzt aufzulösen: Er kopiert alle Einzelteile zum kompletten Programm zusammen, fügt die Aufrufadressen der Funktionen an der aufrufenden Stelle ein (die kennt er ja jetzt, denn jetzt gibt es ja erstmals ein komplettes Programm), ergänzt die fehlenden Teile aus der Systembibliothek und bindet auch deren Aufrufe korrekt ein. Als Ergebnis hast du dann das fertige Programm. > > Kann ich mir das so vorstellen, dass die verschiedenen Quelltextdateien > zu einer einzigen zusammengefügt, heißt die Quelltexte praktisch > hintereinander geschrieben werden? Nicht die Quelltexte. Die vorübersetzten Einheiten. Maschinencode. Mit deinem Programmtext, geschrieben in C, hat der Linker nur noch insofern zu tun, als ihm der Compiler die Einzelteile in Maschinencode übersetzt hat. Aber ansonsten hat der Linker mit C nichts mehr am Hut.
:
Bearbeitet durch User
Danke Karl fuer die schoene Erklaerung. Fuer Christian hier nocheinmal im Detail und mit Bild: http://www.tenouk.com/ModuleW.html MfG
Vielen Dank für die ausführliche Antwort, ok dass der Linker keinen Quelltext sondern Maschinencode vorgesetzt bekommt ist recht einleuchtend. Also zusammengefasst: Der Linker bekommt die kompillierten Programmcodes und die Funktionen aus der Standard-libary, und und und. Dies alles kopiert er dann in eine einzige Maschinencode-Datei (Hex?) zusammen. Also wird aus: Beispiel: Main.o -> 11100101000101 Nichtmain.o -> 101001011110101 Auchnichtmain.o -> 101010111010 Standard-Libary-Funktionen -> 110100010010001100111 dann folgendes: 11100101000101101001011110101101010111010110100010010001100111 (ja ich weiss das ist kein Hex ;-) .Die Speicheradressierung und das drumherum mal ausser acht gelassen) Hab ich das so richtig verstanden?
:
Bearbeitet durch User
Was machen Compiler und Linker? Vielleicht hilft dieses Video: http://et-tutorials.de/938/was-machen-compiler-und-linker/
Christian O. schrieb: > Vielen Dank für die ausführliche Antwort, > > ok dass der Linker keinen Quelltext sondern Maschinencode vorgesetzt > bekommt ist recht einleuchtend. > > Also zusammengefasst: Der Linker bekommt die kompillierten Programmcodes > und die Funktionen aus der Standard-libary, und und und. Dies alles > kopiert er dann in eine einzige Maschinencode-Datei (Hex?) zusammen. Ja. Wobei nicht gesagt ist, dass das 'Hex' (was auch immer das sein soll) sein muss. Es ist ein Binärfile, welches zb im Falle eines Windows-Programms dann auch gleich direkt auf einem Windows-System ausführbar ist. Im konkreten Fall eines Cross-Compilers (also Compiler/Linker die ein Programm erzeugen, welches dann auf einem ganz anderen System läuft), muss dann natürlich das ganze so aufbereitet werden, dass es dann auch tatsächlich in den AVR gebrannt werden kann. > Beispiel: > > Main.o -> 11100101000101 > Nichtmain.o -> 101001011110101 > Auchnichtmain.o -> 101010111010 > Standard-Libary-Funktionen -> 110100010010001100111 > > dann folgendes: > > 11100101000101101001011110101101010111010110100010010001100111 > > (Die Speicheradressierung und das drumherum mal ausser acht gelassen) > > Hab ich das so richtig verstanden? So in etwa. Die Details sind zwar völlig anders, aber vom Prinzip her kommt das schon hin.
:
Bearbeitet durch User
Sehr gut, Vielen Dank euch für die Hilfe...nun hab ich es gerafft ;-) @ Karl Mit Hex meinte ich, dass in fast sämtlichen Artikeln stand, dass die auf den AVR zu übertragende Datei eine .hex-Datei ist. So eine Hex-Datei habe ich auch immer auf den AVR geschrieben. Dachte dass der Code der übertragen wird dann auch im Hexadezimalformat ist. Aber nun hab ich die Informationen die ich suchte. Danke für die schnellen Antworten und Links...Werde mir die Artikel von Stephan und Garden nochmal zur Gemüte führen, die sehen recht interessant aus. Gruß
:
Bearbeitet durch User
Christian O. schrieb: > Mit Hex meinte ich, dass in fast sämtlichen Artikeln stand, dass die auf > den AVR zu übertragende Datei eine .hex-Datei ist. So eine Hex-Datei > habe ich auch immer auf den AVR geschrieben. Dachte dass der Code der > übertragen wird dann auch im Hexadezimalformat ist. > Hier mal noch eine Erläuterung des Intel-Hex-Formates, das für die Programmierfiles (*.hex) in der Regel verwendet wird. Das sind nicht nur die Inhalte des eigentlichen Maschinenprogrammes, sondern auch noch Adressinformationen, Segmentadressen usw. Außerdem ist das ganze auch noch in ASCII codiert, also als Textdatei. http://de.wikipedia.org/wiki/Intel_HEX
Christian O. schrieb: > Mit Hex meinte ich, dass in fast sämtlichen Artikeln stand, dass die auf > den AVR zu übertragende Datei eine .hex-Datei ist. So eine Hex-Datei > habe ich auch immer auf den AVR geschrieben. Dachte dass der Code der > übertragen wird dann auch im Hexadezimalformat ist. Jein. Das Intel-Hex Format ist nur ein Transportformat. Wenn du mit avr-gcc ein Programm für einen AVR compilierst, dann fällt aus dem Linker ein File im ELF Format raus. Das heißt dann z.B. main.elf. Darin steht dann der ausführbare Maschinencode (Section .text), initialisierte Variablen (Section .data) etc. Ebenfalls drin sein können aber auch Debugging-Informationen. Wenn du ein Programm nun in den AVR flashen willst, dann brauchst du dazu mindestens die Teile aus dem ELF File, die in den Flash gehen. Die werden in einem typischen Makefile mit den Programm avr-objcopy aus dem ELF File extrahiert und im Intel HEX Format zwischenspeichert. Das sieht z.B. so aus:
1 | avr-objcopy -O ihex -R .eeprom main.elf main.hex |
Im Prinzip kann das ELF File auch weitere Daten enthalten, die unabhängig vom Flash in den AVR geschrieben werden: - initialisierte EEMEM Variablen - Fuses das braucht dann jeweils andere Aufrufe von avr-objcopy, um die Daten aus dem ELF zu extrahieren. Technisch ist dieser Zwischenschritt mit den HEX Files übrigens nicht nötig. Man könnte auch dem Brennprogramm (z.B. avrdude) beibringen, wie es das ELF File zu zerlegen hat. Allerdings würde man avdude damit wieder fest mit der GNU Toolchain verbandeln. Und da es avr-objcopy ohnehin gibt, hat man sich entschieden, diese Funktionalität nicht zu duplizieren. Ich habe aber auch schon Brennprogramme gesehen, die direkt .elf fressen. XL
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.