I am currently trying to learn assembly programming with MASM64. I have managed to get WriteConsoleA to work, but am stuck trying to use C functions like printf or puts. It should be noted that I am using ml64.exe and link.exe outside of Visual Studio and know that I can create executables successfully.
Here is my code:
includelib <kernel32.lib>
includelib <ucrt.lib>
includelib <legacy_stdio_definitions.lib>
includelib <legacy_stdio_wide_specifiers.lib>
includelib <msvcrt.lib>
includelib <vcruntime.lib>
EXTERN puts: PROC
EXTERN ExitProcess: PROC
EXTERN _CRT_INIT: PROC
.data
message BYTE "Another message! Longer this time!", 0
.code
main PROC
mov rsp, 32 ; Reserve shadow space.
call _CRT_INIT ; Here I call _CRT_INIT because I'm using a custom entry point.
; I know that this call works because commenting it out causes the
; app to crash instantly instead of opening, printing nothing, but
; still waiting a second.
add rsp, 32 ; Remove shadow space.
lea rcx, message ; Load the pointer to my message to the rcx register.
sub rsp, 32 ; Reserve shadow space.
call puts ; Call puts, I know it only takes in a BYTE PTR from the docs.
; The command windows does not crash, it stays open for a moment
; as if the message had been printed, but it is not.
; printf behaves exactly the same as puts here.
add rsp, 32 ; Remove shadow space.
xor rcx, rcx ; Zero out rcx.
call ExitProcess ; End the process.
main ENDP
END
Neither the assembler nor the linker raises an error. As mentioned, my GetStdHandle and WriteConsoleA both work fine. I have tried omitting the _CRT_INIT but that causes the command window to crash instantly upon opening.
Thank you in advance!
UPDATE: For any future traveller (or me) reading this: Please see @RbMm's comment down below, as well as my comment. It turns out that printf definitely did work - it is just that, unlike WriteConsoleA, it causes the window to terminate the exact moment that the printing is complete! Adding a call to Sleep solved everything.