Win32 程序集 - 外部函数命名('@' 的含义)
Posted
技术标签:
【中文标题】Win32 程序集 - 外部函数命名(\'@\' 的含义)【英文标题】:Win32 Assembly - Extern function naming (The meaning of '@')Win32 程序集 - 外部函数命名('@' 的含义) 【发布时间】:2017-02-23 03:17:56 【问题描述】:如我所见,extern
汇编代码中的 WinAPI 函数的名称类似于 _ExitProcess@4
。
@4
部分是什么意思,如何确定@
后面用什么数字?
我知道这与我们链接的 DLL 有关,但在许多情况下,不知道在 @
之后使用什么数字,这会导致许多讨厌的 undefined reference
错误。
【问题讨论】:
【参考方案1】:如果您想获取要使用的数字,请确保您已将 _NT_SYMBOL_PATH 定义为正确的值。
喜欢:
srv*https://msdl.microsoft.com/download/symbols
或
srv*c:\MyServerSymbols*https://msdl.microsoft.com/download/symbols
例如(在cmd.exe、windows命令行中):
set _NT_SYMBOL_PATH=srv*https://msdl.microsoft.com/download/symbols
然后使用:
dumpbin /exports /symbols kernel32.lib | findstr _ExitProcess@
您必须在 kernel32 所在的目录中,并且您必须拥有 grep。
可能是一种使用内置查找命令的方法。您也可以将其重定向到一个文件,然后在您的编辑器中查看它。
【讨论】:
对我不起作用。我刚收到289 120 ExitProcess (forwarded to NTDLL.RtlExitUserProcess)
。
已更正...也需要添加 /symbols
仍然没有运气,我得到与/exports /symbols
相同的结果。
我运行了它,我得到了 kernel32 中大多数函数的修饰名称。 ExitProcess 不是其中之一。
没错。 /export /symbols
还是只给简单的ExitProcess
。【参考方案2】:
正如 Andreas H 的回答所说,@
之后的数字是函数在函数返回之前从堆栈中删除的字节数。这意味着应该很容易确定该数字,因为它也是您需要压入堆栈以正确调用函数的字节数。它应该是调用前的 PUSH 指令数乘以 4。在大多数情况下,这也是传递给函数的参数数乘以 4。
如果您想仔细检查您是否获得了正确的编号并且您安装了 Microsoft Visual Studio,您可以从开发人员命令提示符中找到修饰符号名称,如下所示:
C:\> dumpbin /headers kernel32.lib | find "ExitProcess"
Symbol name : _ExitProcess@4
Name : ExitProcess
如果您使用 MinGW 编译器工具来链接您的汇编代码,您可以这样做:
C:\> nm C:\MinGW\lib\libkernel32.a | find "ExitProcess"
00000000 I __imp__ExitProcess@4
00000000 T _ExitProcess@4
您需要将 C:\MinGW
替换为您安装 MinGW 的目录。
由于并非所有 Windows API 都驻留在 kernel32
导入库中,因此您需要将 kernel32
替换为您要链接到的 API 函数的 Windows SDK 文档中给出的导入库名称。例如,对于 MessageBoxA
,您需要在 Visual Studio 中使用 user32.lib
,在 MinGW 中使用 libuser32.a
。
请注意,很少有不使用 stdcall
调用约定的 Windows API。这些是像 wsprintf
这样的函数,它们接受可变数量的参数,stdcall
调用约定不支持。这些函数的名称前只有一个下划线_
,后面没有@
或数字。它们还要求调用者从堆栈中删除参数。
【讨论】:
【参考方案3】:当为函数指定 stdcall 调用约定时,@ 符号作为前导下划线是函数名的一部分。
数字指定函数从堆栈中删除的字节数。
编译器生成这个数字。
添加后缀是为了避免使用错误的调用约定或源代码中的原型指定错误的参数数量或大小而意外调用该函数。所以目的是提供一种避免程序崩溃的方法。
另见https://msdn.microsoft.com/de-de/library/zxk0tw93.aspx
【讨论】:
以上是关于Win32 程序集 - 外部函数命名('@' 的含义)的主要内容,如果未能解决你的问题,请参考以下文章
error LNK2019: 无法解析的外部符号 _WinMain@16,该符号在函数 ___tmainCRTStartup 中被引用