简体   繁体   English

函数声明中的NASM @符号

[英]NASM @ symbol at function declarations

i'm programming in assembly in NASM, and i found this at code: 我在NASM中进行汇编编程,并在代码中找到了这一点:

extern _ExitProcess@4
;Rest of code...

What @4 means? @4是什么意思? Thanks. 谢谢。

The winapi uses the __stdcall calling convention. winapi使用__stdcall调用约定。 The caller pushes all the arguments on the stack from right to left, the callee pops them again to cleanup the stack, typically with a RET n instruction. 调用者从右向左推动堆栈上的所有参数,被调用者再次弹出它们以清理堆栈,通常使用RET n指令。

It is the antipode of the __cdecl calling convention, the common default in C and C++ code where the caller cleans up the stack, typically with an ADD ESP,n instruction after the CALL. 它是__cdecl调用约定的对立面,后者是C和C ++代码中常见的默认设置,在该约定中,调用方通常在CALL之后使用ADD ESP,n指令清理堆栈。 The advantage of __stdcall is that it is generates more compact code, just one cleanup instruction in the called function instead of many for each call to the function. __stdcall的优点是它会生成更紧凑的代码,被调用函数中只有一条清除指令,而不是每次调用该函数时都会产生许多清除指令。 But one big disadvantage: it is dangerous. 但是一大缺点是:这很危险。

The danger lurks in the code that calls the function having been compiled with an out-dated declaration of the function. 危险隐藏在调用已使用过时的函数声明进行编译的函数的代码中。 Typical when the function was changed by adding an argument for example. 例如,通过添加参数来更改功能时的典型操作。 This ends very poorly, beyond the function trying to use an argument that is not available, the new function pops too many arguments off the stack. 这样的结局很差,除了函数尝试使用不可用的参数外,新函数还会从堆栈中弹出过多的参数。 This imbalances the stack, causing not just the callee to fail but the caller as well. 这会导致堆栈不平衡,不仅导致被调用方失败,而且还会导致调用方失败。 Extremely hard to diagnose. 很难诊断。

So they did something about that, they decorated the name of the function. 因此,他们为此做了一些事情, 装饰了函数的名称。 First with a leading _underscore, as is done for __cdecl functions. 首先使用前导_underscore,对于__cdecl函数也是如此。 And appended @n , the value of n is the operand of the RET instruction at the end of the function. 并在@n后面附加n的值,该值是函数末尾的RET指令的操作数。 Or in other words, the number of bytes taken by the arguments on the stack. 换句话说,参数在堆栈上占用的字节数。

This provides a linker diagnostic when there's a mismatch, a change in a foo(int) function to foo(int, int) for example generates the name _foo@8 . 当不匹配时,这将提供链接程序诊断,例如,将foo(int)函数更改为foo(int, int)生成名称_foo@8 The calling code not yet recompiled will look for a _foo@4 function. 尚未重新编译的调用代码将查找_foo@4函数。 The linker fails, it cannot find that symbol. 链接器失败,无法找到该符号。 Disaster avoided. 避免了灾难。

It's a name decoration specifying the total size of the function's arguments: 这是一个名称修饰,用于指定函数参数的总大小:

The name is followed by the at sign (@) followed by the number of bytes (in decimal) in the argument list. 名称后跟at符号(@),后跟参数列表中的字节数(十进制)。

( source ) 来源

The name decoration scheme for C is documented at Format of a C Decorated Name . C的名称修饰方案记录在C修饰名称的格式中 A decorated name containing a @ character is used for the __stdcall calling convention: 包含@字符的修饰名称用于__stdcall调用约定:

__stdcall : Leading underscore ( _ ) and a trailing at sign ( @ ) followed by a number representing the number of bytes in the parameter list __stdcall :前划线( _ )和后跟符号( @ ),后跟代表参数列表中字节数的数字

Tools like Dependency Walker are capable of displaying both decorated and undecorated names. Dependency Walker之类的工具能够显示修饰名称和未修饰名称。

Unofficial documentation can be found here: Name Decoration 非官方的文档可以在这里找到: 名称装饰

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM