Lowlevel
OffZone => Offtopic => Thema gestartet von: hrungaaz am 28. September 2010, 13:23
-
Servus,
Ich möchte wie bei Teil 2 im Wiki (das letzte Beispiel) eine C-Quelldatei und eine Assembler-Quelldatei kompilieren und linken.
Ich benutze das "normale" MinGW unter Windows.
Folgendermaßen kompiliere, bzw. linke ich das ganze:
gcc main.c -c -o main.o
as fact.S -o fact.o
ld main.o fact.o -o TEST
main.o:main.c:(.text+0xa): undefined reference to `__main'
main.o:main.c:(.text+0x1e): undefined reference to `factorial'
main.o:main.c:(.text+0x36): undefined reference to `printf'
mingw32-make: *** [TEST] Error 1
Kompilieren klappt ja offensichtlich wunderbar, aber beim Linken krachts dann.
Ich weiß nicht warum die drei Funktionen angeblich undefiniert seien, der Quellcode ist ja komplett aus dem Wiki kopiert (ich habe sogar noch die Kommentare drinstehen 8-)).
Oder muss da noch irgendeine (standart) Bibliothek gelinkt werden? Wenn ja - welche?
Könnt ihr mir da weiterhelfen?
Danke schonmal.
mfg rungaaz
[EDIT]
Die Objekte schauen folgendermaßen aus:
fact.o: file format pe-i386
Disassembly of section .text:
00000000 <factorial>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 8b 45 08 mov 0x8(%ebp),%eax
6: 09 c0 or %eax,%eax
8: 75 07 jne 11 <recurse>
a: b8 01 00 00 00 mov $0x1,%eax
f: eb 10 jmp 21 <out>
00000011 <recurse>:
11: 48 dec %eax
12: 50 push %eax
13: e8 e8 ff ff ff call 0 <factorial>
18: 83 c4 04 add $0x4,%esp
1b: 8b 55 08 mov 0x8(%ebp),%edx
1e: 0f af c2 imul %edx,%eax
00000021 <out>:
21: 89 ec mov %ebp,%esp
23: 5d pop %ebp
24: c3 ret
25: 90 nop
26: 90 nop
27: 90 nop
main.o: file format pe-i386
Disassembly of section .text:
00000000 <_main>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 e4 f0 and $0xfffffff0,%esp
6: 83 ec 20 sub $0x20,%esp
9: e8 00 00 00 00 call e <_main+0xe>
e: c7 44 24 1c 05 00 00 movl $0x5,0x1c(%esp)
15: 00
16: 8b 44 24 1c mov 0x1c(%esp),%eax
1a: 89 04 24 mov %eax,(%esp)
1d: e8 00 00 00 00 call 22 <_main+0x22>
22: 89 44 24 08 mov %eax,0x8(%esp)
26: 8b 44 24 1c mov 0x1c(%esp),%eax
2a: 89 44 24 04 mov %eax,0x4(%esp)
2e: c7 04 24 00 00 00 00 movl $0x0,(%esp)
35: e8 00 00 00 00 call 3a <_main+0x3a>
3a: b8 00 00 00 00 mov $0x0,%eax
3f: c9 leave
40: c3 ret
41: 90 nop
42: 90 nop
43: 90 nop
-
Bei alten gcc-Versionen muss man -fno-leading-underscore als Parameter angeben, das dürfte das factorial- und evtl. das printf-Problem beheben, ob es gegen __main hilft, weiß ich nicht.
-
Danke für die Antwort, aber das funktioniert leider auch nicht:
ld main.o fact.o -o TEST -fno-leading-underscore -shared
Cannot export factorial: symbol not defined
main.o:main.c:(.text+0xa): undefined reference to `__main'
main.o:main.c:(.text+0x1e): undefined reference to `factorial'
main.o:main.c:(.text+0x36): undefined reference to `printf'
mingw32-make: *** [TEST] Error 1
Nachdem mir ld folgendes mitgeteilt hat: ld: -f may not be used without -shared
musste ich den genannten Parameter noch dazunehmen, hilft aber auch nicht mehr...
[EDIT]
Warum findet der Linker die Funktionen nicht? Sie sind ja immerhin in den Objekt-Dateien enthalten...
-
Benenne die Funktionen mal mit Unterstrich vorne dran.
-
Wenn dann musst du -fno-leading-underscore dem gcc übergeben. Aber das ist für Windows-Anwendungen nicht korrekt, weil dann die Library-Funktionen nicht mehr gefunden werden. Stattdessen musst du im Assembler-Code _factorial statt factorial schreiben. Die anderen beiden Fehler entstehen, weil ld standardmäßig nicht die nötigen Bibliotheken mitlinkt. Wenn du einfach gcc statt ld verwendest, klappt auch das.
-
Danke, die main- und die printf-Funktionen werden nicht mehr bemängelt, wenn ich mit dem gcc linke.
Aber _factorial (auch mit Unterstrich am Anfang) will auch gcc nicht kennen...
BTW: Welche Bibliotheken werden benötigt, um das ganze mit ld zu linken? libc.a gibt's unter Windows bzw. MinGW nicht, soviel ich gesehen habe.
Und gcc ruft doch zum Linken auch nur den ld auf, somit wäre dann doch wieder alles beim Alten, oder gibt der dann noch die nötigen Libs zum linken per Parameter mit?
[EDIT]
Die Objekt-Datei mit -S und -r gedumpt:
main.o: file format pe-i386
Disassembly of section .text:
00000000 <_main>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 e4 f0 and $0xfffffff0,%esp
6: 83 ec 20 sub $0x20,%esp
9: e8 00 00 00 00 call e <_main+0xe>
a: DISP32 ___main
e: c7 44 24 1c 05 00 00 movl $0x5,0x1c(%esp)
15: 00
16: 8b 44 24 1c mov 0x1c(%esp),%eax
1a: 89 04 24 mov %eax,(%esp)
1d: e8 00 00 00 00 call 22 <_main+0x22>
1e: DISP32 __factorial
22: 89 44 24 08 mov %eax,0x8(%esp)
26: 8b 44 24 1c mov 0x1c(%esp),%eax
2a: 89 44 24 04 mov %eax,0x4(%esp)
2e: c7 04 24 00 00 00 00 movl $0x0,(%esp)
31: dir32 .rdata
35: e8 00 00 00 00 call 3a <_main+0x3a>
36: DISP32 _printf
3a: b8 00 00 00 00 mov $0x0,%eax
3f: c9 leave
40: c3 ret
41: 90 nop
42: 90 nop
43: 90 nop
main hat 3 Unterstriche, _factorial einen zusätzlichen und printf auch einen...
-
Mein Gott, bin ich dumm.
Sorry aber ich hätte den Post von PorkChicken wohl genauer lesen sollen: "[...]Stattdessen musst du im Assembler-Code[...]". Ich hab natürlich auch im C-Code den Unterstrich angefügt...
Jedenfalls funktioniert es jetzt Prima.
Meine einzige Frage ist nur, welche Bibliotheken ich linken muss, um auch mit ld linken zu können?
Danke nochmal für die Hilfen und die Erklärungen.
-
Hi,
gcc scheint zum Linken collect2 (http://gcc.gnu.org/onlinedocs/gccint/Collect2.html) zu verwenden. Der macht sein Ding und ruft dann wiederrum ld auf. Also wenn du weiterhin gcc verwendest, entgehen dir keine Features.
Um deine Frage zu beantworten: Die Parameter, die gcc an collect2 übergibt, bekommst du raus, indem du gcc beim Linken mit dem Parameter -v aufrufst. Bei mir ist das ein ganzer Schwung an Bibliotheken und zusätzlicher Objektdateien. Ich weiß nicht, ob man für ein größeres Projekt damit rumexperimentieren sollte.
-
Wow, Danke!
Werde ich mir auf jeden Fall anschauen, ist nämlich zimlich interessant, was da so alles gelinkt werden muss.
Nochmal Danke!