本文内容概括自IDA pro权威指南第66页到第69页6.2.1节调用约定
调用约定指定函数调用方放置调用函数时所需参数的具体位置(如栈中、寄存器中),此外,还约定了再函数调用结束后由谁负责从栈中删除这些参数。在使用IDA的F5功能时经常能够看到函数签名中带有cdecl、fastcall等字样,这些就是调用约定。调用约定是通常是特定于语言、编译器和CPU的,这里只简单了解一下主流的调用约定。
cdecl) x86体系结构的许多C编译器使用的默认调用约定叫做C调用约定(cdecl)。
cdecl规定:
从右往左放入参数的好处: 第一个参数永远位于栈顶,因此不管需要多少个参数都能最快找到第一个参数,非常适合可变参数的函数,如printf
要求调用方从栈中删除参数的好处: 在可变参数函数的调用时,调用方清楚的知道传入的参数数量,因此能够轻松做出调整,而被调用方无法事先知道自己会收到多少个参数。
stdcall) 标准调用约定的“标准”是由微软为自己的调用约定所起的名称stdcall得来。
stdcall规定:
要求被调用方从栈中删除参数的特点: 被调用方要完成清除参数的任务,必须清楚的知道栈中有多少个参数,只有在函数参数数量固定不变时才有可能。因此,类似printf这种可变参数的函数无法使用stdcall。
stdcall的优点: 在每次函数调用之后,不需要通过代码从栈中清除参数,因而能够生成体积稍小、速度稍快的程序。微软对所有共享库(DLL)文件输出的参数数量固定的函数使用stdcall约定。
x86 fastcall调用约定 fastcall调用约定时stdcall约定的一个变体。
fastcall规定:
thiscall) C++类中的非静态成员函数与标准函数不同,需要使用this指针,该指针指向用于调用函数的对象。用于调用函数的对象的地址必须由调用方提供,因此,他在调用非静态成员函数时作为参数提供。C++语言标准未规定应如何向非静态成员函数传递this指针,因此,不同编译器使用不同的技巧来传递this指针。
略