函数声明中的 NASM @ 符号

Sma*_*vić 0 assembly winapi nasm

我正在 NASM 中进行汇编编程,我在代码中发现了这一点:

extern _ExitProcess@4
;Rest of code...
Run Code Online (Sandbox Code Playgroud)

什么@4意思?谢谢。

IIn*_*ble 5

C 的名称装饰方案记录在C 装饰名称的格式中。包含字符的修饰名称@用于__stdcall调用约定:

__stdcall:前导下划线 ( _) 和尾随符号 ( @) 后跟代表参数列表中字节数的数字

Dependency Walker等工具能够显示修饰名称和未修饰名称。

非官方文档可以在这里找到:名称装饰


Han*_*ant 5

winapi 使用 __stdcall 调用约定。调用者将所有参数从右到左压入堆栈,被调用者再次弹出它们以清理堆栈,通常使用RET n指令。

它是 __cdecl 调用约定的对立面,这是 C 和 C++ 代码中调用者清理堆栈的常见默认值,通常使用 ADD ESP,n在 CALL 之后指令。__stdcall 的优点是它生成更紧凑的代码,在被调用的函数中只需一条清理指令,而不是每次调用该函数时执行许多条清理指令。但是有一个很大的缺点:它很危险。

危险潜伏在调用该函数的代码中,该函数已使用过时的函数声明进行编译。例如,通过添加参数更改函数时的典型情况。这结束得非常糟糕,除了尝试使用不可用参数的函数之外,新函数从堆栈中弹出太多参数。这使堆栈不平衡,不仅导致被调用者失败,也会导致调用者失败。极难诊断。

所以他们做了一些事情,他们修饰了函数的名称。首先使用前导 _underscore,就像对 __cdecl 函数所做的那样。并附加@n, 的值nRET函数末尾指令的操作数。或者换句话说,堆栈上的参数占用的字节数。

这在不匹配时提供链接器诊断,例如foo(int)函数中的更改以foo(int, int)生成 name _foo@8。尚未重新编译的调用代码将查找_foo@4函数。链接器失败,它找不到那个符号。避免了灾难。