下面的句子是否突出显示,是从MASM文档的/ ENTRY页获得的,对吗?

问题描述 投票:0回答:1

/ENTRY(MASM)文档在其“备注”部分中说:

备注

/ ENTRY选项将入口函数指定为开始.exe文件或DLL的地址。

该函数必须定义为使用__stdcall调用约定。

这似乎并不完全正确,因为下面的代码在VS2017中可以正常工作。

.586
.MODEL flat, C
.stack 4096

.CODE
main PROC
    mov eax, -1
main ENDP

END 

其中main被定义为链接器选项/ ENTRY中的代码入口点。请注意,main不使用stdcall调用约定。

突出显示的句子是否仅指用C或C ++编写的代码?

仅出于文档目的,我在用于运行代码的链接器命令行下面提供:

/OUT:"C:\Users\xxxx\Documents\Visual Studio 2017\Projects\Assemblies\Debug\A_test.exe" /MANIFEST
/NXCOMPAT /PDB:"C:\Users\xxxx\Documents\Visual Studio 2017\Projects\Assemblies\Debug\A_test.pdb" 
/DYNAMICBASE "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" 
"shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" /DEBUG:FASTLINK 
/MACHINE:X86 /ENTRY:"main" /INCREMENTAL /PGD:"C:\Users\xxxx\Documents\Visual Studio 
2017\Projects\Assemblies\Debug\A_test.pgd" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" 
/ManifestFile:"Debug\A_test.exe.intermediate.manifest" /ERRORREPORT:PROMPT /NOLOGO /TLBID:1
assembly x86 masm
1个回答
0
投票

部分正确。这里的实际要求稍微复杂一些,并且部分矛盾。对于x86目标,实际入口点代码使用的调用约定对可执行文件并不重要,但需要对DLL使用stdcall调用约定。但是,在x86目标上,使用/ENTRY选项传递的名称将自动修饰,就好像它是cdecl调用函数之后的函数一样,无论是否正在构建可执行文件或DLL。

在x64和ARM目标上,实际上没有stdcall调用约定,因此没有特殊要求,也没有不一致。对于这些目标,入口点代码应遵循标准的cdecl约定,并且不修饰通过/ENTRY选项传递的名称。

入口点汇编代码要求

对于可执行文件,没有参数就调用了入口点,因此调用约定无关紧要,也不影响入口点代码的编写方式。对于DLL,使用三个参数调用入口点,将相同的参数传递给DllMain,并使用stdcall调用约定传递这些参数。在x86目标上,返回时DLL的入口点代码应使用ret 12指令弹出这些参数。

/ ENTRY如何处理其参数

在x86目标(而不是x64和ARM目标)上,/ENTRY链接器选项自动遵循符号名称的cdecl约定在传递的符号前加下划线_作为前缀。即使您正在构建DLL,它也不会添加stdcall @##后缀。然后,它将使该符号与所链接代码中的符号进行模糊匹配。如果使用/ENTRY:foo,它将首先尝试查找名为_foo的符号,如果找不到,它将查找名为foo或以_foo@foo@开头的符号。


关于示例代码的评论

注意,因为您在示例代码中使用.MODEL flat, C,所以MASM会按照x86 cdecl调用约定自动在代码中定义的符号main前面加上下划线_。方便地,这与如上所述的/ENTRY的行为相匹配。但是,命名入口点main并不是最好的主意,因为这暗示着它应该是同名的C函数。由于您的入口入口点没有传递参数,但是C函数main确实会误导您调用入口点main。我建议将其命名为start

最后是在构建32位或64位PECOFF程序时的.STACK directive does nothing useful。仅在创建16位程序时有用。

© www.soinside.com 2019 - 2024. All rights reserved.