Call C standard library function from asm in Visual Studio
Microsoft refactored much of the C runtime and libraries in VS 2015. Some functions are no longer exported from the C library (some are defined in a C header file). Microsoft has some compatibility libraries like legacy_stdio_definitions.lib and legacy_stdio_wide_specifiers.lib, but you can also choose to use the older Visual Studio 2013 platform toolset with the older C libraries.
To change the platform toolset: pull down the Project
menu; select Properties...
; go to Configuration Properties
/General
, and change Platform Toolset
to Visual Studio 2013 (v120)
It appears that it' possible to use the Visual Studio 2015 Toolset with a few modifications.
- You'll need to add these libraries to your dependencies: libcmt.lib, libvcruntime.lib, libucrt.lib, legacy_stdio_definitions.lib. Alternatively you could use
includelib
to include these libraries in your assembly file. - Specify C calling convention for your
main
procedure usingPROC C
- At the end of your file (and this is important) do not use
end main
, useend
only. Not fixing this may cause unexpected crashes. - Although we can use ExitProcess to exit our application, we can also put the return code in EAX and do a
ret
to return. The C runtime calls ourmain
function, and will call the shutdown code for us upon returning.
The code could look like:
.586
.model flat, stdcall
option casemap:none
includelib libcmt.lib
includelib libvcruntime.lib
includelib libucrt.lib
includelib legacy_stdio_definitions.lib
ExitProcess PROTO return:DWORD
extern printf:NEAR
.data
text BYTE "Text", 0
.code
main PROC C ; Specify "C" calling convention
push offset text
call printf
add esp, 4
; invoke ExitProcess,0 ; Since the C library called main (this function)
; we can set eax to 0 and use ret`to have
; the C runtime close down and return our error
; code instead of invoking ExitProcess
mov eax, 0
ret
main ENDP
end ; Use `end` on a line by itself
; We don't want to use `end main` as that would
; make this function our program entry point
; effectively skipping by the C runtime initialization