First off, cl is not a linker but a compiler. Why not just use GoLink as I shown in the post you linked to? It is much easier to use. You could use ld as the linker, but your externs will change a bit.
Windows API functions use function name decorations - an underscore + FunctionName + @sizeof parameters, this is a linker thing.
So, ExitProcess is really exported as _ExitProcess@4 since it takes 1 DWORD parameter. WriteConsoleA takes 5 parameters DWORD sized, so it would be _WriteConsole@20
Change your code to:
extern _ExitProcess@4, _GetStdHandle@4, _WriteConsoleA@20
%define ExitProcess _ExitProcess@4
%define GetStdHandle _GetStdHandle@4
%define WriteConsoleA _WriteConsoleA@20
NULL equ 0
STD_OUTPUT_HANDLE equ -11
section .data
msg db "Hello world!",0xa
msgLen equ $-msg
section .bss
dummy resd 1
section .text
global _main
_main:
push STD_OUTPUT_HANDLE
call GetStdHandle
push NULL
push dummy
push msgLen
push msg
push eax
call WriteConsoleA
push NULL
call ExitProcess
To link with ld, tell it where the lib directory is, a good bet is:
-L "C:Program FilesMicrosoft SDKsWindowsv6.0Lib"
then just use the -l
flag with the library
-l kernel32
My makefile using NASM and ld for your sample code:
APP= Sample
all: $(APP) clean
$(APP): $(APP).obj
"C:MinGWinld" $(APP).obj -o $(APP).exe -L "C:Program FilesMicrosoft SDKsWindowsv6.0Lib" -l kernel32
$(APP).obj: $(APP).asm
nasm -f win32 $(APP).asm -o $(APP).obj
clean:
rm $(APP).obj
If you were to use GoLink as in the other post, you could just use the API Function names as they appear in the docs.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…