According to MS documentation it appears that x86 and x64 assemblies have the same syntax as regards the END
directive, i.e., that both accept an optionally entry point [address] with this directive. But given this issue in GitHub, it seems that x64 doesn't accept this option. The example below shows this:
EXTERN ExitProcess:PROC
.CODE
main PROC
mov eax, 10
exit:
xor ecx, ecx
call ExitProcess
main ENDP
END main
which produces the following error messages in VS2017:
error A2008: syntax error : main
error A2088: END directive required at end of file
IMHO these error messages are very confusing, specially the second one, which seems to say that there is no END
directive in the code.
But assuming that the issue in GitHub is correct, I would like to know whether there was any specific reason for this change in the syntax, from x86 to x64.
This is unfortunately undocumented behaviour for the x64 version of MASM. On this version of the assembler the END directive doesn't accept an entry point symbol. You must simply end your source with a bare "END" statement. (Making the END directive completely useless, as it hasn't been needed to mark the end of the file since MS-DOS 2.0.)
As a workaround, you can specify the entry point with the /ENTRY
linker option, which you can set from the Visual Studio IDE under the project's Property Page -> Linker -> Advanced -> Entry Point. You could also rename your entry point to rely on the linker's default entry point, which depends on the subsystem used, as Microsoft's documentation for /ENTRY states:
By default, the starting address is a function name from the C run-time library. The linker selects it according to the attributes of the program, as shown in the following table.Function name Default for mainCRTStartup (or wmainCRTStartup) An application that uses /SUBSYSTEM:CONSOLE; calls main (or wmain) WinMainCRTStartup (or wWinMainCRTStartup) An application that uses /SUBSYSTEM:WINDOWS; calls WinMain (or wWinMain), which must be defined to use __stdcall _DllMainCRTStartup A DLL; calls DllMain if it exists, which must be defined to use __stdcallIf the /DLL or /SUBSYSTEM option is not specified, the linker selects a subsystem and entry point depending on whether main or WinMain is defined.
If you really want to specify the entry point in the assembly file itself, then you can use the same method the 32-bit x86 version of MASM uses to inform the linker: put a "/ENTRY" option in the .drectve
section. Something like this:
_DRECTVE SEGMENT INFO ALIAS(".drectve")
DB " /ENTRY:main "
_DRECTVE ENDS
Note the spaces around the option.