一、轧名Name mangling和修饰名 Decoration name
在现代编程语言中,许多情况下需要解析程序实体的唯一既定名称,轧名(Name mangling)(又叫命名修饰)是解决这些问题的一种手段。它在函数、结构、类或者其他数据结构的名称中加入额外的信息编码,因此能从编译器传递更多的语义信息给链接器。
轧名允许编程语言在不同的名称空间(不同的作用域)中为不同的实体提供同名的标识符,而不会有命名的冲突。
编译器产生的目标代码(object code)通常会和其他的目标代码相链接,这通常是由链接器来完成的。链接器需要知道每个程序实体的许多信息。例如,为了成功链接一个函数,需要知道的函数的名字、参数的数目、类型等等。
轧名解决了现代编程语言中的很多问题,比如重载等等。它为连接器提供了额外的信息,在编译器和连接器之间传递信息。
Windows平台的C轧名规则
总之,实际上像C一样不支持重载的语言,并不怎么需要轧名。轧名在C语言中可以为函数提供额外信息,比如调用约定(calling conventions)。例如,Windows平台的编译器支持一系列调用约定,这些约定决定了调用参数是如何被传递给子例程并返回的结果。
为什么有调用约定呢?
汇编语言只提供了一条指令,call ptr,其功能是把CS:IP (指令段:指令指针,决定着下一条执行指令的地址)压栈,并且修改CPU的指令指针,作一个跳转。在函数结束的地方,我们使用另一条指令,ret,其功能是把栈中的返回地址取出,并且跳转到那条指令。
不幸的是,汇编语言只提供了指令跳转的命令,作为函数调用另一个重要组成部分的参数传递,其方式就很五花八门了,你可以通过寄存器传值,可以通过调用栈传值,可以通过某一块具体的内存传值(类似全局变量)。然后在被调用函数中,从寄存器,栈或者是内存中读取这些信息。
想象一下如果被调用函数是某一个程序员所编写的,调用者是另一个程序员,那么他俩之间对于参数的传递方式就有了一个约定。
高级语言的出现,把这个问题隐藏了起来。我们在编写一般的c++程序的时候,通常不需要顾虑参数传递的底层实现,但是,这并不意味着这一问题不再出现——我们只是把责任推给了编译器。编译器作为一个计算机程序,总是遵照一定的规则工作,每一个规则对应了一种调用约定,比如一些已经不再被使用的调用约定__fortran,__pascal...
由于这些调用约定之间并不兼容,编译器利用命名变形来标明具体采用了哪一种调用约定。这套轧名规则是由微软建立的,之后为其他各大编译器厂商包括Digital Mars,Borland, and GNU gcc所遵从。这套规则甚至应用到其他的语言,比如Pascal,D,Delphi,Fortran和C#。这些语言编写的子例程,就以种有异于其默认的约定调用呼叫既有的Windows的类库,反之亦然。
int _cdecl f (int x) { return 0; }
int _stdcall g (int y) { return 0; }
int _fastcall h (int z) { return 0; }
使用32为编译器,轧名后的结果为
_f
_g@4
@h@4
stdcall和fastcall的变形规则里,方法名被编码成_name@X和@name@X,其中X是个十进制数,表示的函数参数列表大小(byte)(包括Fastcall中用寄存器传递的参数),而对于cdecl,方法名只是简单的以下划线开头。
分享到:
相关推荐
函数调用约定与函数名称修饰规则是编程中至关重要的概念,尤其在使用C/C++时。函数调用约定,也称为调用约定或调用约定协议,规定了函数调用时参数如何入栈、谁负责清理栈以及如何传递返回值。函数名修饰规则则涉及...
在编写DLL时,如果希望其他语言编写的模块(如Visual Basic、Pascal或Fortran的应用程序)能够调用这些DLL中的函数,那么必须使用正确的调用约定,并避免使用名称修饰,以确保跨语言的互操作性。 #### 三、调用约定...
### 函数调用约定与函数名称修饰规则 #### 调用约定(Calling Convention) 调用约定是指在程序设计语言中为了实现函数调用而建立的一种协议。这种协议规定了该语言的函数中的参数传送方式、参数是否可变以及由谁...
调用约定不仅决定了参数如何传递和栈如何清理,还决定了函数名在汇编语言层面的表示形式,即函数名修饰约定。不同编译器和调用约定下,函数名会被不同的符号修饰。 - **C编译**: - __stdcall:`_functionname@...
C++函数调用约定是编程过程中非常重要的概念,它规定了函数调用时参数传递的顺序、谁负责清理堆栈以及函数名是否需要修饰。在Visual C/C++编译器中,有四种主要的函数调用约定:__cdecl、__stdcall、__fastcall和...
在链接和调试过程中,编译器会根据调用约定来修饰函数名,以便于区分不同的调用约定。例如: - 对于 `_cdecl`,装饰后的名字为 `_functionname`。 - 对于 `_stdcall`,装饰后的名字为 `_functionname@number`。 - ...
C_C++函数符号生成规则(函数名的修饰);C++ 函数重载.pdf 本文主要介绍了C和C++函数符号生成规则,以及C++函数重载机制。 一、C函数符号生成规则 在C语言中,函数符号生成规则主要有三种:cdecl调用约定、std ...
在C和C++编程中,函数的调用约定(Calling Convention)和函数名修饰规则(Decorated Name)是两个至关重要的概念,它们直接影响到程序的链接和执行过程。当混合使用C和C++代码,或者在C++程序中调用第三方非C++库时...
在C编译时,函数名修饰约定规则为: * __stdcall调用约定在输出函数名前加上一个下划线前缀,后面加上一个“@”符号和其参数的字节数,格式为_functionname@number。 * __cdecl调用约定仅在输出函数名前加上一个...
Windows调用约定是指Windows平台下函数调用时的规则和约定,它是编译器在生成函数调用代码时遵循的一套机制,以确保调用方与被调用方之间能够正确地传递参数和处理函数返回值。在C++和C语言中,这些调用约定对程序的...
了解这些调用约定后,开发者可以根据需要选择合适的约定,比如在编写DLL或Win API函数时通常使用`stdcall`,以确保与其他使用相同约定的函数兼容。而在一般C/C++程序中,如果不指定,默认使用`cdecl`。对于追求性能...
### C++调用约定详解:理解C++中的不同调用方式 #### 一、引言 在C++编程中,函数调用约定是一种规范化的机制,用于规定如何传递参数、如何清理栈空间以及如何确定函数名称等。这些约定对程序员来说至关重要,尤其...
在C编译时,不同的调用约定会导致不同的名字修饰规则,而在C++编译时,修饰名更为复杂,通常涉及更多的元数据信息,如函数类型、成员函数等。 在C++中,_stdcall调用约定的修饰名以"?"开头,接着是函数名,然后是"@...
例如,如果一个C++函数被C代码调用,那么应使用extern "C"来指定cdecl约定,以避免名称修饰和调用约定不匹配的问题。 在VC7.0, VC7.1, VC8.0, 和 VC6这些Visual C++版本中,开发者可以通过编译器选项来选择不同的...
函数名经过特定的命名修饰,通常在函数名前加前导下划线,并附带一个@符号和参数总大小。例如,对于函数int function(int a, int b),其在使用stdcall调用约定后,编译器会将其命名为_function@8(其中8代表参数总...
在程序设计领域中,函数调用规则,也称为调用约定,是指在函数调用过程中一系列预定义的行为规范。这些规范主要包括如何将参数压入堆栈、由谁负责清理堆栈以及如何进行返回值处理等。在不同的编程环境中,这些调用...
4. 函数名修饰:`stdcall`函数也会进行名称修饰,但与`cdecl`不同,它的修饰规则是为了适应Windows API,一般不会包含参数类型信息,而是以`@`符号后跟参数总字节数表示。 在C#中,虽然没有直接使用`cdecl`或`...
DLL(Dynamic Link Library)是Windows操作系统中的一个重要特性,它允许将多个函数和其他资源打包到一个单独的库中,供多个程序共享使用,从而减少内存占用和提高效率。本篇文章将详细探讨DLL的创建以及函数调用...