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 mitextern "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.