【笔记】函数调用

调用约定

cdecl调用约定

x86体系结构的许多c编译器使用的默认调用约定是c调用约定。如果默认的调用约定被重写,则C/C++程序中常用的_cdecl修饰符会迫使编译器利用c调用约定。这种调用约定叫做cdecl调用约定。cdecl调用约定:调用方按从从右向左的顺序将函数参数放入栈中,在被调用的函数完成其操作时,调用方负责从栈中清除参数。

stdcall调用约定

这种约定在函数调用时使用_stdcall修饰符。stdcall调用约定规定:调用方按从右向左的顺序将函数参数放在程序栈上,在被调用的函数完成操作时,被调用方负责从栈中清楚参数,返回值在eax寄存器中。要完成这个任务,被调用的函数必须知道栈中有多少个参数,这只有在函数接收的参数数量不变时才有可能。因此,printf这种接受数量可变的参数的函数不能使用stdcall调用约定。根据惯例,微软对所有由共享库(DLL)文件输出的参数数量固定的函数使用stdcall约定。

x86fastcall约定

fastcall约定是stdcall约定的一个变体,它向CPU寄存器(而非程序栈)最多传递两个参数。如果指定使用fastcall约定,则传递给函数的前两个参数将分别位于ECX和EDX寄存器中。剩余的其他参数则以类似于stdcall约定的方式从右向左放入栈中,在被调用的函数完成操作时,被调用方负责从栈中清楚参数。

c++调用约定

c++类中的非静态成员函数与标准函数不同,它们需要使用this指针,该指针指向用于调用函数的对象。用于调用函数的对象的地址必须由调用方提供,因此,他在调用非静态成员函数时作为参数提供。thiscall调用约定,将this传递到ECX寄存器中,并且和在 stdcall中一样,他要求非静态成员函数清除栈中的参数。GNU g++编译器将this看成是任何非静态成员函数的第一个隐含参数,而在所有其他方面与使用cdecl约定相同。因此,对使用g++编译的代码来说,在调用非静态成员函数之前,this被防止到栈顶,且调用方负责在函数返回时删除栈中的参数(至少有一个参数)。

你可能感兴趣的:(【笔记】函数调用)