;this file -> test1.asm
includelib msvcrt.lib
includelib legacy_stdio_definitions.lib
extern _CRT_INIT: proc ;custom entrypoint needs c-runtime to be initialised by the programmer.
extern printf: proc
extern ExitProcess: proc
.data
msg db "hello world!", 13, 10, 0
.code
fun proc
sub rsp, 32 ;for shadow space
call _CRT_INIT ;called _CRT_INIT because I have my own entry point named "fun"
lea rcx,msg
call printf
add rsp, 32
call ExitProcess
fun endp
end
commandline for assembler: ml64 /nologo /c test1.asm
commandline for linker: link /entry:fun /subsystem:console test1.obj
This standalone assembly program seems to be working fine. But doing some changes(mentioned below) make the program crash.
1st change -> according to this link both libcmt.lib and msvcrt.lib statically links the native CRT startup (ie both can be used to call _CRT_INIT) into my code. The difference is msvcrt.lib is used with dll. As I don't have any dll I considered using libcmt.lib in place of msvcrt.lib but then the program crashes. Considering there is only printf function associated, that concludes printf function breaks the program. But why?
2nd change -> Now I tried calling this fun() function from a simple .C file. For that I made the necessary changes.
;this file -> test1.asm
;not including any libraries. linking the .c file make the libraries link too because that is in my libpath environment variable
;extern _CRT_INIT: proc ;no need of _CRT_INIT because now mainCRTStartup() will be the entrypoint and .c file will take care of initializing the c-runtime
extern printf: proc
;extern ExitProcess: proc ;no need of exitprocess. Instead i'm using ret instruction because I'm calling fun() from .c file.
.data
msg db "hello world!", 13, 10, 0
.code
fun proc c ;even if I replace 'c' with something like "abed" the program works. but if I dont give anything after proc then the program crashes.
sub rsp, 32 ;for shadow space
lea rcx,msg
call printf
add rsp, 32
ret
fun endp
end
//this file -> test2.c
#include <stdio.h>
#include <conio.h>
void fun(); //in C no need of extern keyword. extern is needed in c++
int main()
{
fun();
getch();
}
commandline for assembler: ml64 /nologo /c test1.asm
commandline for compiler: cl /nologo /c test2.c
commandline for linker: link test1.obj test2.obj
In the previous working example (ie. with msvcrt.lib) I don't have to give any suffixes after 'proc' directive. But in this case when I am calling 'fun' as a function from my C file I need to give anything like 'a'/'b'/combination('abcd') after 'proc' directive and only then the program works. If I don't give anything after 'proc' the program crashes. According to official MSDN documentation proc directive also accept language type. Even so wrong/random 'language type name' ie. any word seem to work. But how?
I tried many things like changing the libraries, using different version of printf (like vfprintf) and tried assigning more shadow space also googled much but unable to find any answer.