函数声明中的NASM @符号

时间:2013-09-15 12:45:46

标签: winapi assembly nasm

我在NASM的程序集编程,我在代码中找到了这个:

extern _ExitProcess@4
;Rest of code...

@4的含义是什么? 感谢。

3 个答案:

答案 0 :(得分:4)

winapi使用__stdcall调用约定。调用者从右向左推送堆栈上的所有参数,被调用者再次弹出它们以清理堆栈,通常使用RET n指令。

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

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

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

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

答案 1 :(得分:3)

这是一个名称装饰,用于指定函数参数的总大小:

  

名称后跟at符号(@),后跟参数列表中的字节数(十进制)。

source

答案 2 :(得分:3)

C的名称装饰方案记录在Format of a C Decorated Name。包含@字符的修饰名称用于__stdcall调用约定:

  

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

Dependency Walker这样的工具能够显示装饰和未装饰的名称。

非官方文档可在此处找到:Name Decoration