Linking to Kernel32.lib in assembler

assembly, nasm, winapi

Solution

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 Files\Microsoft SDKs\Windows\v6.0\Lib"

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:\MinGW\bin\ld" $(APP).obj -o $(APP).exe -L "C:\Program Files\Microsoft SDKs\Windows\v6.0\Lib" -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.

Problem

I started learning assembly today and have ran many tests on linux that worked very well! I moved over to my PC and started to attempt to write some here. I ran into a problem when attempting to call external functions (which again, worked fine on linux) where I would get LINK 2001 Unresolved External errors telling me that WriteConsoleA is not defined when after compiling with nasm: ``` nasm -f win32 test.asm -o test.obj ``` and with cl.exe: ``` cl test.obj /link libcmt.lib kernel32.lib ``` I get these errors: ``` test.obj : error LNK2001: unresolved external symbol ExitProcess test.obj : error LNK2001: unresolved external symbol GetStdHandle test.obj : error LNK2001: unresolved external symbol WriteConsoleA test.exe : fatal error LNK1120: 3 unresolved externals ``` The assembly: ``` extern ExitProcess, GetStdHandle, WriteConsoleA 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 ``` Copied almost exactly from here. Any help is much appreciated! Thanks!

Original source

Related problems