I am trying to compile a hello world on windows with the ML and LINK that ship with VS 2010.
.MODEL FLAT
.STACK 4096
.data
msg db "Hello World!",0
.code
INCLUDELIB MSVCRT
EXTRN printf:NEAR
EXTRN exit:NEAR
PUBLIC _main
_main PROC
mov eax, offset msg
push eax
call printf
mov eax,0
push eax
call exit
_main ENDP
END _main
I keep getting linker errors saying that printf and exit are unresolved external symbols. I have a couple of questions.
- What are the command line options to use with ML and LINK to compile and resolve the error messages.
- Is there another way to display text output to the screen using assembly code rather than calling c runtime functions like printf?
- You need to use underscored names for C functions, since that's how the compiler emits them on assembly
level.
- You should clean up the stack after calling printf and other CRT functions, since they use cdecl calling convention (caller stack cleanup). Strictly speaking you should do it after _exit too, but that's less important since it never returns.
- To use CRT functions you have to initialize CRT. You can check how it's done in the file
VC\crt\src\crt0.c
Here's a minimal file that worked for me (I used static library because I have VS2008 and didn't want to fiddle with manifests to make it work with DLL).
.386
.MODEL FLAT
.STACK 4096
.data
msg db "Hello World!",0
.code
INCLUDELIB LIBCMT
EXTRN _printf:NEAR
EXTRN _exit:NEAR
EXTRN __heap_init:NEAR
EXTRN __mtinit:NEAR
EXTRN __ioinit:NEAR
PUBLIC _main
_main PROC
push 1
call __heap_init
add esp, 4
push 1
call __mtinit
add esp, 4
call __ioinit
mov eax, offset msg
push eax
call _printf
pop ecx
mov eax,0
push eax
call _exit
_main ENDP
END _main
For MSVCRT the initialization is different, e.g. you need to call set_app_type
To not rely on CRT, you have to use the OS APIs. In case of Win32 that would be Win32 functions such as WriteFile (with GetStdHandle(STD_OUTPUT_HANDLE) for the file handle). See some examples here.