调用约定


调用约定

  本文内容概括自IDA pro权威指南第66页到第69页6.2.1节调用约定

  调用约定指定函数调用方放置调用函数时所需参数的具体位置(如栈中、寄存器中),此外,还约定了再函数调用结束后由谁负责从栈中删除这些参数。在使用IDA的F5功能时经常能够看到函数签名中带有cdeclfastcall等字样,这些就是调用约定。调用约定是通常是特定于语言、编译器和CPU的,这里只简单了解一下主流的调用约定。

C调用约定(cdecl

  x86体系结构的许多C编译器使用的默认调用约定叫做C调用约定(cdecl)。

cdecl规定:

  • 调用方将所需参数放入栈中
  • 参数放入顺序为从右往左v
  • 调用结束后由调用方清除参数

从右往左放入参数的好处: 第一个参数永远位于栈顶,因此不管需要多少个参数都能最快找到第一个参数,非常适合可变参数的函数,如printf

要求调用方从栈中删除参数的好处: 在可变参数函数的调用时,调用方清楚的知道传入的参数数量,因此能够轻松做出调整,而被调用方无法事先知道自己会收到多少个参数。

标准调用约定(stdcall

  标准调用约定的“标准”是由微软为自己的调用约定所起的名称stdcall得来。

stdcall规定:

  • 调用方将所需参数放入栈中
  • 参数放入顺序为从右往左
  • 调用结束后由被调用方清楚参数

要求被调用方从栈中删除参数的特点: 被调用方要完成清除参数的任务,必须清楚的知道栈中有多少个参数,只有在函数参数数量固定不变时才有可能。因此,类似printf这种可变参数的函数无法使用stdcall

stdcall的优点: 在每次函数调用之后,不需要通过代码从栈中清除参数,因而能够生成体积稍小、速度稍快的程序。微软对所有共享库(DLL)文件输出的参数数量固定的函数使用stdcall约定。

x86 fastcall调用约定

  fastcall调用约定时stdcall约定的一个变体。

fastcall规定:

  • 能够将最多两个参数存放在寄存器中
  • 传递给函数的前两个参数将分别位于ECX和EDX寄存器中
  • 剩余参数以类似于stdcall约定的方式从右往左放入栈上

C++调用约定(thiscall

  C++类中的非静态成员函数与标准函数不同,需要使用this指针,该指针指向用于调用函数的对象。用于调用函数的对象的地址必须由调用方提供,因此,他在调用非静态成员函数时作为参数提供。C++语言标准未规定应如何向非静态成员函数传递this指针,因此,不同编译器使用不同的技巧来传递this指针。

其他调用约定


文章作者: 大A
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 大A !
评论
  目录