Win32程序集 - 外部函数命名('@'的含义)

问题描述:

正如我所见,extern汇编代码中的WinAPI函数的名称有[email protected]Win32程序集 - 外部函数命名('@'的含义)

@4部分的含义是什么,以及如何确定在@之后要使用哪个数字?

我知道这与我们链接的DLL有关,但在很多情况下,我们不知道在@之后使用了什么数字,这会导致许多令人讨厌的undefined reference错误。

参见如安德烈亚斯ħ回答说@后的数字是一个字节的函数返回之前的号码的功能从栈中删除。这意味着应该很容易确定该数字,因为它需要的字节数也会推送到堆栈上以正确调用该函数。它应该是调用之前PUSH指令的数量乘以4.在大多数情况下,这也将是传递给函数的参数的数量乘以4。

如果要仔细检查你已经得到了正确的数字,你有微软的V​​isual Studio安装,你可以找到从开发人员命令提示符这样的装饰符号名称:

C:\> dumpbin /headers kernel32.lib | find "ExitProcess" 
    Symbol name : [email protected] 
    Name   : ExitProcess 

如果”重新使用MinGW的编译工具链接你的汇编代码,你可以这样做,而不是:

C:\> nm C:\MinGW\lib\libkernel32.a | find "ExitProcess" 
00000000 I [email protected] 
00000000 T [email protected] 

你需要在你安装MinGW的目录,以取代C:\MinGW

由于并非所有Windows API都驻留在kernel32导入库中,您需要用Windows SDK文档中给出的导入库的名称替换kernel32,以获取要链接到的API函数。例如,对于MessageBoxA,您需要在Visual Studio中使用user32.lib,而在MinGW中使用libuser32.a

请注意,有几种罕见的Windows API不使用stdcall调用约定。这些功能类似于wsprintf,其采用可变数量的参数,其中stdcall调用约定不支持。这些函数名称前只有一个下划线_,并且没有@或之后的数字。他们还要求调用者从堆栈中移除参数。

+0

这种方法确实有效。 – hakeris1010

如果您想获取要使用的号码,请确保将_NT_SYMBOL_PATH定义为正确的值。

喜欢:

srv*https://msdl.microsoft.com/download/symbols 

srv*c:\MyServerSymbols*https://msdl.microsoft.com/download/symbols 

例如(在cmd.exe的,窗口的命令行):

set _NT_SYMBOL_PATH=srv*https://msdl.microsoft.com/download/symbols 

然后使用:

dumpbin /exports /symbols kernel32.dll | grep -i ExitProcess 

你必须在kernel32所在的目录下,你必须有grep。

可能是一种使用内置find命令的方法。你也可以将它重定向到一个文件,然后在你的编辑器中查看它。

+0

不适合我。我只是得到'289 120 ExitProcess(转发给NTDLL.RtlExitUserProcess)'。 –

+0

更正了......需要添加/符号 –

+0

仍然没有运气,我用'/ exports/symbols'得到了同样的结果。 –

当为函数指定stdcall调用约定时,@符号是作为前导下划线的函数名称的一部分。

该数字指定函数从堆栈中移除的字节数。

编译器生成此编号。

添加了后缀,以便函数不会被意外地调用错误的调用约定,或者源代码中的原型指定错误的参数数目或大小。所以意图是提供避免程序崩溃的手段。

https://msdn.microsoft.com/de-de/library/zxk0tw93.aspx