Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |
Autor |
Nachricht |
diciani

Anmeldungsdatum: 05.03.2008 Beiträge: 9 Wohnort: Berlin
|
Verfasst am: 06.03.2008, 00:52 Titel: manuelles Linken |
|
|
Hallo. Ich hab im Forum nichts gefunden und mich darauf mal bei euch hier angemeldet.
Kann mir jemand etwas von seinem Wissen über das Linken in FreeBasic vermitteln?
Ich habe schon herausgefunden, wie man den Compiler anweist, Assembler-code oder objektdateien auszugeben, aber wie ich die obj-Dateien jetzt verlinken soll ist mir ein Rätsel (wenn ich mir mal den asm-code dazu anschaue).
Mein Ziel: (Free-)BASIC-code und zB C-code miteinander verlinken, ohne den Umweg über DLLs zu nehmen. Das funktioniert bei mir zwar prima, aber ein besseres Verständnis und die Möglichkeit, ohne DLLs auszukommen wären mir lieber.
Mal ein einfaches Beispiel, erst BASIC, dann asm-code daraus:
Code: | PRINT "Hello World!" |
Code: | .intel_syntax noprefix
.section .text
.balign 16
.globl _main
_main:
push ebp
mov ebp, esp
and esp, 0xFFFFFFF0
sub esp, 4
mov dword ptr [ebp-4], 0
call ___main
push 0
push dword ptr [ebp+12]
push dword ptr [ebp+8]
call _fb_Init@12
.Lt_0001:
push 1
push 12
push offset _Lt_0003
call _fb_StrAllocTempDescZEx@8
push eax
push 0
call _fb_PrintString@12
.Lt_0002:
push 0
call _fb_End@4
mov eax, dword ptr [ebp-4]
mov esp, ebp
pop ebp
ret
.section .data
.balign 4
_Lt_0003: .ascii "Hello World!\0"
|
Der Einsprungpunkt scheint main zu heißen. Sehr überraschend.
Also den hätten wir schonmal.
So, aber was ist nun mit den Funktionsaufrufen? PrintString zB...
Ich nehme mal an, diese Funktionen stecken in irgendwelchen obj-Dateien, sodass die Funktionen einfach immer bei Bedarf dazugelinkt werden.
Aber wo finde ich die? Und warum finde ich einen solchen Funktionsaufruf im fertigen Programm nicht wieder, wenn ich es mir anschaue?
Falls jemand weis, wie das funktioniert oder mir sonst helfen kann wäre ich dankbar  |
|
Nach oben |
|
 |
Elektronix
Anmeldungsdatum: 29.06.2006 Beiträge: 742
|
Verfasst am: 06.03.2008, 11:22 Titel: |
|
|
Das _main stammt aus der Programmsprache C, da muß ein Hauptprogramm immer in eine Funktion int main() gepackt werden (in Basic hieße das: Function main () as Integer.)
Beim Linken werden nur die .obj-Dateien miteinander verknüpft und einige Systemdateien bzw. .dlls dazugebunden. In denen finden sich auch die von Dir bewunderten Funktionen (printString).
Linken kannst Du eigentlich mit jedem Linker, ob von Borland C, Dev-C++, QuickBasic o. ä.. Soweit ich weiß, kann aber FreeBasic selbst auch linken. Es hat nur keinen eigenen Linker, sondern die Funktion ist im Compiler eingebaut. _________________ Und die Grundgebihr is aa scho drin- DOS is jo nett. |
|
Nach oben |
|
 |
diciani

Anmeldungsdatum: 05.03.2008 Beiträge: 9 Wohnort: Berlin
|
Verfasst am: 06.03.2008, 12:44 Titel: |
|
|
Danke für deine Antwort.
Nur wie kann ich denn aus meiner hello.o eine hello.exe machen mit einem anderen Linker? Beim linken muss ich ja alle Obj-dateien und libs mit angeben, wo code drinsteckt, der benutzt wird.
Welche muss ich denn da nehmen? In den 6 o-dateien in lib/win32 gibt es printString zB garnicht. Deine einzige Datei im fbc-ordner, wo zB printString nochmal drin vorkommt ist fbc.exe. Vielleicht ist das schon in fbc.exe eingebaut?
Ich möchte ja aber gerade einen anderen linker benutzen können um die Vorteile aus 2 Sprachen miteinander zu verbinden  |
|
Nach oben |
|
 |
Elektronix
Anmeldungsdatum: 29.06.2006 Beiträge: 742
|
Verfasst am: 06.03.2008, 12:50 Titel: |
|
|
Ob das wirklich Vorteile bringt, ist meist keine Frage der Sprachen oder des Linkers, sondern des Umgangs mit ihnen. Letztendlich machen alle Linker das Gleiche. Welche Vorteile eine Sprache bietet, entscheidet sich vorher beim Compilieren.
Das Linken geht normalerweise mit der Zeile: Code: |
Link Datei1.obj datei2.obj Exename.exe | Genaueres steht aber in den Dokus zu den jeweiligen Linkern. Beim QuickBasic-Linker läßt sich das relativ leicht heraufinden, da stehts in der Online-Hilfe. _________________ Und die Grundgebihr is aa scho drin- DOS is jo nett. |
|
Nach oben |
|
 |
diciani

Anmeldungsdatum: 05.03.2008 Beiträge: 9 Wohnort: Berlin
|
Verfasst am: 06.03.2008, 15:24 Titel: |
|
|
Genau, das weiss ich doch auch alles...
Ich weiss nur nicht, welche datei2.obj datei3.obj usw. ich nehmen soll.
Datei1.obj muss natürlich erstmal meine hallo.obj sein, in meinem Beispiel mit den "Hello World!"-Programm jetzt.
Aber PrintString zB steckt in keinen Obj.-Dateien in FreeBasic, sondern scheinbar nur in der fbc.exe.
Ob ich damit recht habe und wie man dann damit umgeht ist ja gerade meine Frage.
Wie man linker benutzt und was sie machen weiss ich ja auch alles selber...  |
|
Nach oben |
|
 |
Elektronix
Anmeldungsdatum: 29.06.2006 Beiträge: 742
|
Verfasst am: 06.03.2008, 15:52 Titel: |
|
|
Wenn fbc.exe PrintString enthält, liegt die vielleicht genau in der Link-Funktion von fbc. Ich würde vorschlagen, Du probierst es einfach mal aus, ob dein Prog sich auch mit anderen Linkern verarbeiten läßt. Wenn ja, heißt das, daß PrintString eben von den Linkern selbst eingefügt wird. Viel kaputt machen kannste ja nicht. _________________ Und die Grundgebihr is aa scho drin- DOS is jo nett. |
|
Nach oben |
|
 |
volta
Anmeldungsdatum: 04.05.2005 Beiträge: 1876 Wohnort: D59192
|
Verfasst am: 06.03.2008, 16:00 Titel: |
|
|
Hi diciani,
es werden nur sehr wenig Module direkt vom FBC dazugelinkt (siehe: FreeBasicVerzeichnis\lib\win32\*.o Dateien).
Meistens werden Funktionen aus DLL's genutzt.
Für ein einfache "? Hello Word" Programm zeigt ein Disassembler:
Disassembler hat Folgendes geschrieben: | +++++++++++++++++++ IMPORTED FUNCTIONS ++++++++++++++++++
Number of Imported Modules = 3 (decimal)
Import Module 001: KERNEL32.dll
Import Module 002: MSVCRT.DLL
Import Module 003: USER32.dll
+++++++++++++++++++ IMPORT MODULE DETAILS +++++++++++++++
Import Module 001: KERNEL32.dll
Addr:00010230 hint(0001) Name: AddAtomA
Addr:0001023C hint(0012) Name: Beep
Addr:00010244 hint(009B) Name: ExitProcess
Addr:00010254 hint(00A9) Name: FillConsoleOutputAttribute
Addr:00010274 hint(00AA) Name: FillConsoleOutputCharacterA
Addr:00010294 hint(00AF) Name: FindAtomA
Addr:000102A0 hint(00DC) Name: GetAtomNameA
Addr:000102B0 hint(010D) Name: GetConsoleMode
Addr:000102C4 hint(010F) Name: GetConsoleScreenBufferInfo
Addr:000102E4 hint(0142) Name: GetLargestConsoleWindowSize
Addr:00010304 hint(0182) Name: GetStdHandle
Addr:00010314 hint(0242) Name: PeekConsoleInputA
Addr:00010328 hint(025A) Name: ReadConsoleInputA
Addr:0001033C hint(0282) Name: ScrollConsoleScreenBufferA
Addr:0001035C hint(0294) Name: SetConsoleCtrlHandler
Addr:00010374 hint(0297) Name: SetConsoleCursorPosition
Addr:00010390 hint(02A1) Name: SetConsoleMode
Addr:000103A4 hint(02AA) Name: SetConsoleWindowInfo
Addr:000103BC hint(02DF) Name: SetUnhandledExceptionFilter
Addr:000103DC hint(02EB) Name: Sleep
Addr:000103E4 hint(032C) Name: WriteConsoleInputA
Addr:000103FC hint(0330) Name: WriteConsoleOutputA
Addr:00010414 hint(0336) Name: WriteFile
Import Module 002: MSVCRT.DLL
Addr:00010420 hint(003B) Name: __getmainargs
Addr:00010430 hint(0046) Name: __mb_cur_max
Addr:00010440 hint(0052) Name: __p__environ
Addr:00010450 hint(0054) Name: __p__fmode
Addr:00010460 hint(0069) Name: __set_app_type
Addr:00010474 hint(0090) Name: _assert
Addr:00010480 hint(009A) Name: _cexit
Addr:0001048C hint(00A8) Name: _controlfp
Addr:0001049C hint(00D3) Name: _fileno
Addr:000104A8 hint(00DE) Name: _fmode
Addr:000104B4 hint(00E1) Name: _fpreset
Addr:000104C0 hint(0111) Name: _iob
Addr:000104C8 hint(0113) Name: _isctype
Addr:000104D4 hint(0186) Name: _onexit
Addr:000104E0 hint(018F) Name: _pctype
Addr:000104EC hint(01B3) Name: _setmode
Addr:000104F8 hint(0250) Name: abort
Addr:00010500 hint(0257) Name: atexit
Addr:0001050C hint(025C) Name: calloc
Addr:00010518 hint(0265) Name: exit
Addr:00010520 hint(0274) Name: fprintf
Addr:0001052C hint(027A) Name: free
Addr:00010534 hint(02AD) Name: malloc
Addr:00010540 hint(02B5) Name: memset
Addr:0001054C hint(02C3) Name: realloc
Addr:00010558 hint(02CB) Name: signal
Addr:00010564 hint(02DA) Name: strlen
Addr:00010570 hint(02EF) Name: tolower
Addr:0001057C hint(02F0) Name: toupper
Import Module 003: USER32.dll
Addr:00010588 hint(01A7) Name: MapVirtualKeyA
Addr:0001059C hint(0268) Name: VkKeyScanA |
EDIT/ Freebasic benutzt den Linker ld.exe aus den GNU Binutils . _________________ Warnung an Choleriker:
Dieser Beitrag kann Spuren von Ironie & Sarkasmus enthalten.
Zu Risiken & Nebenwirkungen fragen Sie Ihren Therapeuten oder Psychiater. |
|
Nach oben |
|
 |
diciani

Anmeldungsdatum: 05.03.2008 Beiträge: 9 Wohnort: Berlin
|
Verfasst am: 06.03.2008, 16:46 Titel: |
|
|
Vielen Dank, das ist doch schonmal was
KERNEL32.dll, MSVCRT.DLL und USER32.dll sind ja alles DLLs von Mircosoft und Teil der WinAPI.
PrintString zB ist da sicherlich nicht zu finden
Aber der Tipp mit GNU ld ist sehr interessant. Wenn FreeBASIC ld benutzt, muss man ja einen Aufruf finden können, mit dem ich das auch manuell und selber machen kann. Wo hast du die Informationen her? Vielleicht finde ich da ja noch was...
Wo bekomme ich jetzt die richtigen Module her? Ohne diese wird der Linker allerlei Fehler wie "Error: unresolved symbol 'PrintString' vorhanden..." oder so ähnlich ausspucken  |
|
Nach oben |
|
 |
raph ael
Anmeldungsdatum: 12.04.2006 Beiträge: 472
|
Verfasst am: 06.03.2008, 17:09 Titel: |
|
|
Link es mal mit Code: | FreeBASIC\lib\win32\fbrt0.o |
|
|
Nach oben |
|
 |
diciani

Anmeldungsdatum: 05.03.2008 Beiträge: 9 Wohnort: Berlin
|
Verfasst am: 06.03.2008, 17:21 Titel: |
|
|
Linker Aufruf
Code: | D:\Dev-Cpp\bin>D:\Dev-Cpp\bin\ld.exe "D:\2008-märz\Hello World!.o" D:\FreeBASIC\lib\win32\fbrt0.o -o hello.exe |
Linker-Ausgabe:
Code: | D:\Dev-Cpp\bin\ld.exe: warning: cannot find entry symbol _mainCRTStartup; defaulting to 00401000
D:\2008-mõrz\Hello World!.o(.text+0xa):fake: undefined reference to `fb_StrAllocTempDescZEx@8'
D:\2008-mõrz\Hello World!.o(.text+0x12):fake: undefined reference to `fb_PrintString@12'
D:\FreeBASIC\lib\win32\fbrt0.o(.text+0x5):fbrt0.c: undefined reference to `fb_hRtInit'
D:\FreeBASIC\lib\win32\fbrt0.o(.text+0x15):fbrt0.c: undefined reference to `fb_hRtExit' |
Wie erwartet findet er PrintString, usw. nicht.  |
|
Nach oben |
|
 |
raph ael
Anmeldungsdatum: 12.04.2006 Beiträge: 472
|
Verfasst am: 06.03.2008, 17:38 Titel: |
|
|
Dann Link mal folgende O's aus dem Lib- Verzeichnis mit:
- dllcrt2.o
- fbrt0.o
- gcrt2.o
|
|
Nach oben |
|
 |
diciani

Anmeldungsdatum: 05.03.2008 Beiträge: 9 Wohnort: Berlin
|
Verfasst am: 06.03.2008, 17:53 Titel: |
|
|
Ich hab einfach mal alle dazugelinkt.
Effekt: alle möglichen unaufgelöste Symbole in den 6 o-dateien, was mich aber erstmal nicht stört und die beiden Symbole aus meiner hallo.o wurden auch wieder nicht mit aufgelöst. In den 6 o-dateien in Freebasic/lib/win32 steht ja auch nichts von zB PrintSting oder StrAllocTempDescZEx, da wundert es mich auch garnicht, dass es nicht geht.
Code: | ...
D:\2008-mõrz\Hello World!.o(.text+0xa):fake: undefined reference to `fb_StrAllocTempDescZEx@8'
D:\2008-mõrz\Hello World!.o(.text+0x12):fake: undefined reference to `fb_PrintString@12'
... |
Aber irgendwie anders muss man es doch trotzdem hinbekommen können, das ist doch eine recht grundlegende Sache, dass man die erstellten Obj.-Dateien auch zusammenlinken kann.
Sonst sind erstens die und auch die Assemblate ja nutzlos  |
|
Nach oben |
|
 |
raph ael
Anmeldungsdatum: 12.04.2006 Beiträge: 472
|
Verfasst am: 06.03.2008, 18:28 Titel: |
|
|
Hab grade eine nicht ganz umgesetze Idee.
Ich habe einfach ld.exe (FreeBASIC's LD) durch ein waaaahnsinnig simples Programm ersetzt: Code: | Open "ld.txt" For Output As #1
Print #1, Command
Close #1 |
Dann habe ich die LD.EXE umbenannt und die neu erstellte newld.exe in ld.exe umbenannt und das obenstehende Programm nochmals compiliert. Folge: LD's Aufruf wurde in ld.txt gespeichert:
Code: | -T C:\freebasic\freebasic\bin\win32\i386pe.x -subsystem console -s --stack 1048576,1048576 -L C:\freebasic\freebasic\lib\win32 -L ./ C:\freebasic\freebasic\lib\win32\crt2.o C:\freebasic\freebasic\lib\win32\crtbegin.o newld.o -o newld.exe -( -lfb -lgcc -lmsvcrt -lkernel32 -lmingw32 -lmingwex -lmoldname -lsupc++ C:\freebasic\freebasic\lib\win32\fbrt0.o -) C:\freebasic\freebasic\lib\win32\crtend.o |
Wie gesagt, nicht GANZ umgesetzt. Aber das sollte helfen. |
|
Nach oben |
|
 |
diciani

Anmeldungsdatum: 05.03.2008 Beiträge: 9 Wohnort: Berlin
|
Verfasst am: 06.03.2008, 18:43 Titel: |
|
|
Eine Ausgezeichnete Idee
Ich werde auch gleich mal damit rumspielen
edit/
Beim Versuch damit zu linken sucht er nur noch WinMain. Das sollte doch eigentlich eine Konsolenanwendung werden ("-subsystem console")!?
Code: | D:\FreeBASIC\lib\win32/libmingw32.a(main.o):main.c:(.text+0x97): undefined reference to `WinMain@16' |
Aber dieses Problem gefällt mir schon viel besser. |
|
Nach oben |
|
 |
raph ael
Anmeldungsdatum: 12.04.2006 Beiträge: 472
|
Verfasst am: 07.03.2008, 23:32 Titel: |
|
|
Du erstellst eine Konsolenanwendung aber das heißt noch lange nicht, dass es nicht eine Windows- Anwendung ist . Es ist einfach eine Windows- Anwendung die in einer Konsole ausgeführt wird. Benenne einfach den Eintrittspunkt in "WinMain" um. Das könnte ein guter Weg sein, um an iCmdShow ranzukommen, aber das hat mit diesem Thema nix zu tun. _________________
Zitat: | 1000 Yottabytes sind absurd. 640 Yottabytes sollten genug für jeden sein. |
|
|
Nach oben |
|
 |
diciani

Anmeldungsdatum: 05.03.2008 Beiträge: 9 Wohnort: Berlin
|
Verfasst am: 08.03.2008, 16:35 Titel: |
|
|
Du hast ja recht. Ich mag WinMain nicht, das verwirrt mich jedes Mal
Ich habe einfach mal fix eine leere WinMain erstellt, die ich jetzt dazu linke, damit er nicht meckert. Mittels --unresolved-symbols=ignore-all müsste das zwar laut Hilfe auch ohne diesen Trick gehen, aber das funktioniert komischerweise nicht.
Code: | #include <windows.h>
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow )
{
return 0;
} |
Wenn ich jetzt in C zB ein Programm los schreibe,
Code: | extern int main();
void los(){
// hier kann beliebiger Kram hin
main(); // <-- Mein BASIC Programm (zB "Hello World!" von oben)
// hier kann auch beliebiger Kram hin
return;} |
alle Obj.-Dateien zusammenlinke und als Einsprungpunkt __Z3losv wähle, dann hab ich wieder ein "Hello World!"-Programm. Ich kann nun also BASIC-code problemlos und schnell in meinem C-Programmen verwenden, es beliebig mixen.
Sehr sehr schick.
Genau das wollte ich. Vielen Dank an raph ael, du hast mir sehr geholfen, ich wär so schnell nicht auf die Idee gekommen, auch wenn sie einfach war.
Bei Gelegenheit muss ich mich nochmal etwas mit Linkerscripts beschäftigen, damit ich das von FreeBASIC auch verstehe. Im Moment verwende ich es nur, also ohne es wirklich zu verstehen.
PS: Was ist iCmdShow? Das sagt mir garnichts?
edit/
lol, Ich habs ja eben praktisch selbst verwendet, es beinhaltet scheinbar Informationen über das Fenster (minimiert, Vollbild, ...). Dass es das aber auch bei Konsolenanwendungen gibt...?! |
|
Nach oben |
|
 |
raph ael
Anmeldungsdatum: 12.04.2006 Beiträge: 472
|
Verfasst am: 08.03.2008, 16:51 Titel: |
|
|
iCmdShow ist ein Wert der von Windows an das Programm übergeben wird. Er wird mit von ShowWindow verwendet und sagt, wie das Fenster angezeigt werden soll (maximiert, minimiert, normal). Ich kenne keine Methode wie man das in FB abfragen kann. _________________
Zitat: | 1000 Yottabytes sind absurd. 640 Yottabytes sollten genug für jeden sein. |
|
|
Nach oben |
|
 |
Elektronix
Anmeldungsdatum: 29.06.2006 Beiträge: 742
|
Verfasst am: 09.03.2008, 00:12 Titel: |
|
|
Klasse, von dem Thread konnte ich auch noch dazulernen.
Man sollte aber dazu sagen, daß dieses hybrid-verlinkte Program nur in der DOSBox von Windows funktioniert, nicht unter DOS (z. B. FreeDOS), weil das die Funktion WinMain und die ganzen zugehörigen Parameter nicht kennt.
Im Ordner win32 finden sich logischerweise nur Dateien, die sich auf Windows beziehen. Wenn Du ein DOS-Prog willst, findet sich vielleicht anderswo noch etwas entsprechendes.
iCmdShow wird bei der API-Funktion ShowWindow() benutzt, um den Anzeigestatus eines Fensters zu ändern. Die Optionen sind:
SW_HIDE
SW_MAXIMIZE
SW_MINIMIZE
SW_RESTORE
SW_SHOW
SW_SHOWDEFAULT
SW_SHOWMAXIMIZED
SW_SHOWMINIMIZED
SW_SHOWMINNOACTIVE
SW_SHOWNA
SW_SHOWNOACTIVATE
SW_SHOWNORMAL
Diese Optionen sollten sich mit einer normalen select-case-Routine abfragen lassen. Mit "Print iCmdShow" geht das nicht, das ergibt nur einen Integerwert, mit dem Du nichts anfangen kannst. Die Optionen sind in Windows.bi per #define den jeweiligen Interern zugeordnet. _________________ Und die Grundgebihr is aa scho drin- DOS is jo nett. |
|
Nach oben |
|
 |
|