I would like to compile the Hello World NASM example on windows.
I've pasted the code above into a main.asm
file, and compiled it into an obj file with this command:
nasm -fwin32 .\main.asm -o main.obj
After that I wanted to compile this obj file to an exe, like this:
g++ .\main.obj -o main.exe -m32
But I get this error:
C:/Program Files (x86)/mingw-w64/i686-8.1.0-posix-dwarf-rt_v6-rev0/mingw32/bin/../lib/gcc/i686-w64-mingw32/8.1.0/../../../../i686-w64-mingw32/lib/../lib/libmingw32.a(lib32_libmingw32_a-crt0_c.o):crt0_c.c:(.text.startup+0x39): undefined reference to `WinMain@16'
What do I miss? How is it possible to fix this error?
That Hello World program is trying to create the PE import table manually. In order for that to work, you need to instruct the linker carefully (the PE sections are not tied to PE directories, idata
is just a name).
Further assumptions are made in that source (e.g. the base address of the image and the need for the CRT).
Honestly, it's just nonsense. Use the linker properly, like Jester shown.
Being really honest, that whole Wikipedia section is just informational at best.
Long story short: never use Wikipedia as a programming tutorial.
EDIT: The x86-64 Linux example on the Wikipedia page has been updated by Peter Cordes; the others may still be misleading.
You can create a 32-bit Windows console program mainly in two ways:
Use the C run time (CRT)
This lets you use the common C functions (above all printf
).
There are two ways to use the CRT:
main
/WinMain
/DllMain
and unicode variants) is being called by the CRT that runs first by a properly set PE entry-point)._mainCRTStartup
that initialize the CRT and the CRT calls your main function.msvcrt.dll
for the version shipped with Windows installation or msvcrtXX0.dll
for the version shipped with Visual Studio installation (where XX
depends on the VS version).Use only the Windows API
The Windows API are the OS exposed functions, these are what the CRT implementation ends up calling.
You can use the Windows API and the CRT (the common scenario is for a graphical application to have the CRT statically linked and use WinMain
as the entry-point - where the Windows APIs are intermixed with C utility functions) or the Windows API alone.
When using them alone you get a smaller, faster and easy to make executable.
To use 1.1 you need the CRT object files and these are usually shipped with a compiler (they once were shipped with the Windows SDK but now that VS is free Microsoft moved them in the VS package - fair but VS is orders of magnitude more heavy than the SDK).
1.2 and 2 don't need these object files.
Note however that compilers/assemblers/linkers compatibility may be a nasty beast, especially the .lib
machinery for linking external APIs (basically libs file are a way to make the linker find the functions that will be resolved by the loader at runtime - i.e. those defined in an external DLL).
First, to write Hello, World! using the method 2., see this other answer of mine.
It was written when a linker was available in the Windows SDK, today I use GoLink.
It is a minimalist, very easy to use, linker.
One key point of it is that it doesn't need the .lib files, instead you can pass it the path of the DLLs where the external functions reside.
The NASM command is the same, to link use:
golink /console /entry main c:\windows\system32\kernel32.dll hello.obj -fo hello.exe
Untested - optionally add /largeaddressaware
if you code can handle that
That example is for 64-bit programming, it's more involved than a 32-bit one but may be useful anyway.
This is what the Wikipedia article is trying to use.
Before analyzing that specific code, let me show how I'd write it:
BITS 32
GLOBAL _main
EXTERN printf
EXTERN exit
SECTION .text
_main:
push strHelloWorld
call printf
add esp, 04h
push 0
call exit
SECTION .data
strHelloWorld db "Hello, world!", 13, 10, 0
This is pretty straightforward compared to the Wiki's one.
To make an executable:
nasm -fwin32 helloworld.asm -o helloworld.obj
golink /console /entry _main c:\windows\system32\msvcrt.dll helloworld.obj -fo helloworld.exe
The Wikipedia's code is creating an .idata
sections that stores the PE Import Address Table.
This is a silly move, the linker is used to generate that table based on the dynamic dependencies of the object files.
To make that program link we need to:
0x400000
. This can be done with any linker (for golink use /base 0x400000
)..text
section starts. I don't know if link.exe
can take .text
as a valid symbol name or if allows to specify an entry-point relative to .text
but that seems very unlikely. Golink won't allow for that. In short a label is probably missing..idata
section. I'm not aware of any linker that would allow for that (though it may exists).In short, forget about it.
This is what the link Jester pointed out is using.
The assembly code is the same as for 1.2 but you use MinGW for linking.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With