ld: Linken mit User32.dll



  • 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 vor jz .

    cmp $0, %eax
    jz .error
    

    Aber Danke für deine sonstige Hilfe, oenone.


Anmelden zum Antworten