这个/ENTRY (MASM) 文件在其备注部分说:
评论
/ENTRY 选项将入口点函数指定为 .exe 文件或 DLL 的起始地址。
该函数必须定义为使用 __stdcall 调用约定。
这似乎并不完全正确,因为下面的代码在 VS2017 中没有问题。
.586
.MODEL flat, C
.stack 4096
.CODE
main PROC
mov eax, -1
main ENDP
END
Run Code Online (Sandbox Code Playgroud)
其中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
Run Code Online (Sandbox Code Playgroud)
这是部分正确的。这里的实际要求相当复杂,部分矛盾。对于 x86 目标,实际入口点代码使用的调用约定对可执行文件无关紧要,但需要对 DLL 使用 stdcall 调用约定。但是,在 x86 目标上,与该/ENTRY选项一起传递的名称会被自动修饰,就好像它是遵循 cdecl 调用约定的函数一样,无论是生成可执行文件还是 DLL。
在 x64 和 ARM 目标上,实际上没有 stdcall 调用约定,因此没有特殊要求,也没有不一致。入口点代码应该遵循这些目标的标准 cdecl 约定,并且与/ENTRY选项一起传递的名称没有被修饰。
在可执行文件的情况下,入口点是不带参数调用的,因此 cdecl 和 stdcall 调用约定是等效的,因此任何一个都可以用于入口点代码。在 DLL 的情况下,入口点使用三个参数调用,相同的参数传递给DllMain,这些参数使用 stdcall 调用约定传递。在 x86 目标上,DLL 的入口点代码应ret 12在返回时使用指令弹出这些参数。
在 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改为命名它。
最后,.STACK 指令在构建 32 位或 64 位 PECOFF 程序时没有任何用处。它仅在创建 16 位程序时有用。
| 归档时间: |
|
| 查看次数: |
50 次 |
| 最近记录: |