Assemblieren und Linken bei Windows



  • Hello,

    Ich probiere gerade verschiedene Möglichkeiten aus, ein Hello World Programm in Windows zu assemblieren und zu linken. Da gibt es ja scheinbar einige Möglichkeiten, und ich wüsste gerne, was ihr für die Praktikabelste haltet.

    Möglichkeiten, die ich bisher entdeckt habe, mit unterschiedlichen Objektdateien und Linkern:

    Methode 1

    global ..start
    
    extern MessageBoxA
    
    import MessageBoxA User32.dll 
    
    section .text use32
    
    ..start: 
    
    push 0
    push the_title
    push msg
    push 0
    call [MessageBoxA]
    ret
    
    section .data 
    
    the_title  db "HelloWorldProgram", 0  
    msg        db "Hello World! ", 13, 10, 0 
    msg_len    dd 0
    

    nasm -fobj datei.asm
    alink -oPE datei.obj

    Hier muss ich komischerweise immer das use32 für 32 bit bei section .text dazuschreiben, sonst funktioniert es nicht.
    Außerdem ist das die einzige Methode, wo ich den import Befehl brauche und in der asm-Datei die dlls angeben muss die benutzt werden. In diesem Fall die User32.dll für MessageBoxA.

    Methode 2

    global start
    
    extern MessageBoxA
    
    section .text
    
    start: 
    
    push 0
    push the_title
    push msg
    push 0
    call MessageBoxA
    ret
    
    section .data 
    ...
    

    nasm -fwin32 datei.asm
    golink datei.obj user32.dll

    Hier spar ich mir den import Befehl und dll in der asm-Datei und muss die benötigte dll stattdessen beim Linker angeben.
    Komischerweise funktioniert hier "..start" nicht, nur "start"

    Methode 3

    global _WinMain@16
    
    extern _MessageBoxA@16
    
    section .text 
    
    _WinMain@16: 
    
    push 0
    push the_title
    push msg
    push 0
    call _MessageBoxA@16
    ret
    
    section .data
    ...
    

    nasm -f elf datei.asm
    gcc -o datei.exe datei.o

    Hier brauch ich ebenfalls keinen import Befehl, und muss die benötigten dlls noch nicht mal beim Linker angeben. Dafür ist das @16 bzw. allgemein @zahl nach jeder Funktion, das seltsamerweise auf einmal nötig wird, extrem nervig. Und ich dürfte auch Schwierigkeiten haben die richtige Zahl für jede Funktion zu ermitteln.
    Außerdem komisch und überflüssig, dass man da jetzt unbedingt "_WindowsMain@16" statt "start" als entry point braucht, aber naja.

    Dass wären also die Methoden, die ich bisher gefunden habe. Kennt ihr vielleicht was Besseres?

    Ich muss noch dazu sagen, dass ich Assembler mit C/C++ verbinden will, was möglicherweise auch eine Rolle spielt. Hab was von einer Konvention gehört, dass man immer den Underscore _ vor Funktionen/Routinen setzen muss, damit der assembler code zu C/C++ kompatibel ist. Diese Bedingung erfüllt aber nur die 3 Methode, die anderen 2 Methoden funktionieren hingegen nicht, wenn ich z.B. "_start" schreibe.



  • climits schrieb:

    Hab was von einer Konvention gehört, dass man immer den Underscore _ vor Funktionen/Routinen setzen muss, damit der assembler code zu C/C++ kompatibel ist.

    C tut das, C++ nicht mehr. Der Sinn war genau, dass man Assembler mit C zusammen benutzen kann und es keine Namenskollisionen gibt. In C++ gibt es Überladung, sodass die Funktionen eh anders heißen müssen als sie im Code stehen, sodass der Unterstrich nicht mehr nötig ist.
    Du kannst C++ sagen, dass es die C-Style Unterstrichnamen verwenden soll mit

    extern "C"{
    //mit C benamste funktionen
    }
    

    Die C-Variante ist nämlich deutlich einfacher, dafür sind Überladungen futsch.
    Dann wirst du dich noch mit calling conventions auseinander setzen müssen, ist nicht schwer, darf man nur nicht vergessen.


Anmelden zum Antworten