João Afonso
João Afonso

Reputation: 1934

Why am I getting this error in the assembly code below?

This is my first trial running an assembly code for x64 in MASM:

_text SEGMENT
main PROC
    mov ah,0
    ret
main ENDP
_text ENDS
END

and I'm getting a linker error LNK2001: unresolved external symbol mainCRTStartup. Why?

I have the entry point main in Properties > Linker > Advanced > Entry Point

P.S.: the code assembles and executes as expected in x86.

Upvotes: 1

Views: 702

Answers (1)

vengy
vengy

Reputation: 2259

There's an entry point (_mainCRTStartup) within the C-Runtime library (CRT) libcmt.lib, which does some initialization tasks, and then hands off control to the entry point for your application main. You can change the default entry point, but usually you want the convenience of the initialization the CRT entry point does for you automatically.

There are two methods to avoid LNK2001: unresolved external symbol mainCRTStartup.

  1. Add libcmt.lib to the link command:
    (C-Runtime initialization calls main)

    ml64.exe test64.asm /link /DEBUG /subsystem:console /defaultlib:kernel32.lib /defaultlib:user32.lib /defaultlib:libcmt.lib

  2. Specify the entry point main on the link command:
    (Avoids C-Runtime initialization and calls main)

    ml64.exe test64.asm /link /DEBUG /subsystem:console /defaultlib:kernel32.lib /defaultlib:user32.lib /entry:main

Here's some example MASM64 code to popup a window:

test64.asm

option casemap:none

externdef MessageBoxA : near
externdef ExitProcess : near

   .data
   
    szDlgTitle    db "MASM 64-bit",0
    szMsg         db "HELLO",0   

   .code

main proc
   ; Reserve 28h bytes of shadow space.
   sub  rsp, 28h       
   xor  r9d, r9d       
   lea  r8, szDlgTitle  
   lea  rdx, szMsg    
   xor  rcx, rcx       
   call MessageBoxA
   add  rsp, 28h

   ; rax contains the ExitCode from MessageBoxA(...)

   ; When the primary thread's entry-point function main returns,
   ; it returns to the C/C++ Runtime startup code,
   ; which properly cleans up all the C Runtime resources used by the process.
   ; 
   ; After the C Runtime resources have been freed,
   ; the C Runtime startup code explicitly calls ExitProcess,
   ; passing it the value returned from the entry-point function. 
   ; This explains why simply returning from the primary thread's entry-point function terminates the entire process.
   ; Note that any other threads running in the process terminate along with the process.

   ret
   
main endp

end

To build test64.exe, I use these batch commands:

makeit64.bat

@echo on

if not defined DevEnvDir (
  call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Auxiliary\Build\vcvars64.bat"
)

ml64.exe test64.asm /link /subsystem:console /defaultlib:kernel32.lib /defaultlib:user32.lib /defaultlib:libcmt.lib

The output is

hello_masm

Upvotes: 2

Related Questions