Environment: Windows 10. I happen to be using a MinGW version of ld
for linking, but I'm happy to use the visual studio link.exe
if it makes things simpler.
I have the following basic program in nasm:
global _main
extern _printf
section .text
_main:
push message
call _printf
add esp, 4
ret
message:
db 'Hello, World', 10, 0
And it builds fine using
nasm -f win32 test.nasm
When trying to link it to the windows CRT (ucrt.lib), I get the following error:
$ ld -o test.exe test.obj
test.obj:test.nasm:(.text+0x6): undefined reference to `printf'
Ok, so I need to point the linker at the ucrt library:
$ ld -o test.exe /c/Program\ Files\ \(x86\)/Windows\
Kits/10/Lib/10.0.14393.0/ucrt/x86/ucrt.lib test.obj
test.obj:test.nasm:(.text+0x6): undefined reference to `printf'
Trying the equivalent with the visual studio linker:
d:\Code\nasm>link -out:test.exe -entry:main -subsystem:console test.obj
Microsoft (R) Incremental Linker Version 14.10.25017.0
Copyright (C) Microsoft Corporation. All rights reserved.
test.obj : error LNK2001: unresolved external symbol _printf
test.exe : fatal error LNK1120: 1 unresolved externals
This raises a couple of questions:
Why does one of these try to find
printf
and the other,_printf
? I get that there's an underscore convention, but it doesn't seem to be understood by both linkers.I used
objdump -t
to look at the symbols in the ucrt.lib file. I won't paste the entire list, but it contains entries such as:
[ 4](sec 1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000 __imp____conio_common_vcprintf
[ 5](sec 3)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000 ___conio_common_vcprintf
[ 4](sec 1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000 __imp____conio_common_vcprintf_p
Neither printf
nor _printf
appears in the list. Does this mean it's not exported by that library? If not, which library should I be linking?
According to this MS article, ucrt.lib
is the de-facto library for the c runtime and C standard library.
Thanks to a comment from Michael Petch, it looks like I need to manually link 1 or more extra libs which are in a completely separate location from the
ucrt.lib
library. The relevant one for printf islegacy_stdio_definitions.lib
, which I found deep in a sub-dir of my VS2017 install directory, as opposed to theucrt.lib
which is in the Windows SDK install directory.The definition of
printf
is provided inline instdio.h
unless the macro_NO_CRT_STDIO_INLINE
is defined, which I guess it usually is when building inside the VS toolchain.