ld: Linken mit User32.dll
-
Hallo,
ich habe in Assembler ein kleines Programm geschrieben, das laut den Beschreibungen von MSDN ausschließlich Funktionen aus User32.dll nutzt.Der Assembler erzeugt, wie erwartet, eine Objektdatei. Jetzt will ich die Objektdatei mit dem
ld
linken, und zwar mit User32.dll.Ich habe diese Datei im Explorer gesucht und festgestellt, dass die einzige Datei unter diesem Namen im Ordner
C:\Windows\System32
zu finden ist.Ich rufe
ld
mit folgenden Parametern auf:
ld input.o -LC:\Windows\System32 -lUser32
Der ld gibt allerdings trotzdem Fehlermeldungen aus: "undefined references to ..."
Ich habe in der Assemblerdatei die externen Funktionen mittels ".extern" kenntlich gemacht, also
.extern FunktionsName
1. Ist das so ok, oder muss es heißen:
.extern _FunktionsName
2. Ich habe beide Schreibweisen ausprobiert, beidemale gibt
ld
diese Fehlermeldungen.3. Wo liegt nun das Problem?
-
Was für einen Assembler benutzt du? Warum benutzt du nicht Link.exe?
z.B. mit NASM und Link.exe wäre folgendes möglich:
nasm -fwin32 hello.asm link /subsystem:console /nodefaultlib /entry:main hello.obj
Was für undefined references werden denn gelistet? Sicher, dass die nicht aus kernel32 kommen und du das auch mitlinken musst?
-
Ich genutze den
as
und denld
.... und ich habe keine Ahnung, was "Link.exe" ist.
Laut MSDN ist die Funktion aus windows.h, und in der Library User32.lib, als DLL User32.dll.
-
Achso, du benutzt die GNU Tools. In Cygwin?
Wie geschrieben würde mich immernoch interessieren, welche Referenzen nicht gefunden werden.
-
Nicht Cygwin, sondern Mingw.
Ich nutze in meinem kleinen Programm genau 3 Funktionen, alle sind aus User32.dll, und bei allen dreien werden Fehlermeldungen ausgegeben.
Ich vermute eher, dass ich die Funktionen mit ".extern" nicht richtig angebe.
Wie gesagt, ich verstehe nicht, ob man die Funktionen einfach unter ihrem Funktionsnamen, wie er eben in windows.h steht, oder mit "_Funktionsname" angeben soll.
-
Eigentlich musst du die User32-Lib von MinGW linken und nicht die aus C:\Windows. Die sollte unter C:\MinGW\lib liegen (libuser32.a oder ähnlich).
Wegen den Funktionen: Benutzt du das Include user32.inc?
Kannst du vielleicht einen Beispielcode posten?
Hier ist ein Beispiel mit MsgBox und ExitProcess (letzteres benötigt kernel32): http://www.asmcommunity.net/forums/topic/?id=29731
Vielleicht hilft dir das weiter.
-
oenone schrieb:
Eigentlich musst du die User32-Lib von MinGW linken und nicht die aus C:\Windows. Die sollte unter C:\MinGW\lib liegen (libuser32.a oder ähnlich).
Die Datei ist da, aber wie linke ich sie?
-llibuser32 funktioniert nicht, -luser32 auch nicht.
Und mingw hat keine user32.inc, deshalb muss ich ja die benötigten Funktionen selbst als extern deklarieren.
-
Assembler-Lerner schrieb:
Die Datei ist da, aber wie linke ich sie?
-llibuser32 funktioniert nicht, -luser32 auch nicht.
Eigentlich genauso wie du es ursprünglich versucht hast: -LC:\MinGW\lib -lUser32
Assembler-Lerner schrieb:
Und mingw hat keine user32.inc, deshalb muss ich ja die benötigten Funktionen selbst als extern deklarieren.
Die meisten C-Compiler fügen den _ an. Das dürfte bei den Win32-Funktionen auch der Fall sein, also musst du .extern _FunktionsName benutzen.
-
Leider besteht das Problem weiterhin.
-
Ohne Quellcode kann ich dir glaube ich nicht weiterhelfen.
Ich hab es aber auch mal ausprobiert:
hello.asm:
.extern _MessageBoxA@16 .extern _ExitProcess@4 .section .data window_title: .ascii "Message box\0" window_message: .ascii "It works!!!\0" .section .text .globl _start _start: # displays a message box push $0x0 push $window_title push $window_message push $0x0 call _MessageBoxA@16 movl $0x0, %eax # exit push $0x0 call _ExitProcess@4
Dann assemblen und linken:
as -o hello.o hello.asm ld -o hello.exe hello.o -LC:\MinGW\lib -luser32 -lkernel32 hello.exe
... und eine MsgBox popt hoch mit dem Text.
Funktioniert das bei dir auch so?
-
Ich habe das Beispiel auch kompiliert, und es funktionert auch bei mir.
Dazu noch kurz eine Frage: Wie kann ich verhindern, dass, wenn ich das Programm starte, im Hintergrund ein Konsolenfenster aufpoppt? Beim gcc kann man das verhindern, wenn man beim Kompilieren "-mwindows" angibt. Aber wie kann man das beim Linken erzielen?Und noch eine Frage:
Was genau sagen die Zahlen hinter den per.extern
deklarierten Dateinamen?oenone schrieb:
.extern _MessageBoxA@16 .extern _ExitProcess@4
Also das "@16" und das "@4"?
Hat das was mit den Parametern zu tun, die die Funktion verlangt, also "ExitProcess" verlang als Parameter 4 Bytes, also einen Int?
Hättest du vielleicht einen Link zur Gnu-Assembler-Dokumentation, wo das erklärt ist?
-
Probier mal "--subsystem windows", um das Konsolenfenster zu umgehen. Bei meinem Test kam übrigens keins, da ich die exe schon aus einem Konsolenfenster aufgerufen habe ^^'
Du hast richtig geraten, die Zahl ist die Anzahl an Bytes. Das liegt nicht an GAS oder Assembler, sondern an der Win-API:
http://msdn.microsoft.com/de-de/library/zxk0tw93.aspx(Siehe "Namensergänzungskonvention", da steht auch das mit dem "_")
-
Ok, und wenn eine Funktion keinen Parameter annimmt (
void
), dann "@0"?
-
Genau
-
Das Program ist trivial, es soll einfach nur das Clipboard leeren.
.extern _OpenClipboard@4 .extern _EmptyClipboard@0 .extern _CloseClipboard@0 .extern _ExitProcess@4 .section .text .globl _start _start: push $0 call _OpenClipboard@4 jz .error call _EmptyClipboard@0 jz .error call _CloseClipboard@0 push $0 call _ExitProcess@4 .error: push $1 call _ExitProcess@4
Es lässt sich mittlerweile kompilieren, es scheint aber nicht zu funktioneren.
Wenn ich einen Text in die Zwischenablage kopiere, und dann das Programm starte, so bleibt der Text in der Zwischenablage
Vielleicht könntest du mir ein weiteres mal helfen?
-
Ich habe meinen Fehler selbst gefunden: ich muss natürlich erstmal den Rückgabewert der Funktionen mit
cmp
überprüfen vorjz
.cmp $0, %eax jz .error
Aber Danke für deine sonstige Hilfe, oenone.