Contents
  1. 1. 一.基本介绍
  2. 2. 二.函数调用约定
    1. 2.1. 0x01Windows_x86下的函数调用约定(C)
      1. 2.1.1. -cdecl调用约定
      2. 2.1.2. -stdcall调用约定
      3. 2.1.3. -fastcall调用约定
    2. 2.2. 0x02Windows_x64下的调用约定(C)
      1. 2.2.1. -fastcall调用约定
    3. 2.3. 0x03LINUX_X64下的函数调用约定
    4. 2.4. 0x04C++调用约定
      1. 2.4.1. -thiscall调用约定

一.基本介绍

函数调用约定,是指当一个函数被调用时,函数的[参数]会被传递给被调用的函数和[返回值]会被返回给调用函数。函数的调用约定就是描述参数是怎么传递和由谁平衡[堆栈]的,当然还有返回值。

二.函数调用约定

0x01Windows_x86下的函数调用约定(C)

-cdecl调用约定

(c语言默认的函数调用方式)调用函数后,使用

1
ASS ESP,XXX

整理栈。
调用者直接清理压入栈的函数参数。
好处:它可以像c语言中printf()函数一样,向被调用函数传递长度可变的参数。

-stdcall调用约定

(常用于Win32 API,该方式由被调用者清理栈)如果想使用stdcall方式编译源码,只要使用_stdcall关键字即可。
eg建立函数:

1
int _stdcall add(int a, int b)

栈的清理工作由函数最后的

1
RETN 8

(该命令含义:RETN + POP 8 字节)来执行。
好处:被调用者函数内部存在着栈清理代码,代码尺寸小。

-fastcall调用约定

(与stdcall类似,但该方式通常使用寄存器传参)头两个参数(从左到右)存入ECX和EDX,余下的参数存入栈中(从右到左)。
好处:可以实现函数的快速调用(对于CPU,访问寄存器比访问内存快很多)。
劣处:寄存器在调用函数前若存有重要数据,或者有其他用途,需要将寄存器中的数据先备份。

0x02Windows_x64下的调用约定(C)

-fastcall调用约定

x64下的调用约定简化了,一律使用_fastcall,前四个参数用ECX, RDX, R8, R9传递,除了这四个外加RAX, R10, R11,其他寄存器都是非易失的。

0x03LINUX_X64下的函数调用约定

参数从左到右放入寄存器:RDI, RSI, RDX, ECX, R8, R9。当参数为7个以上时,前6个与前面一样,但后面的依次从“右向左”放入栈中。

0x04C++调用约定

-thiscall调用约定

(c++特有的一种调用约定,用于类成员函数的调用约定)如果参数确定,this指针存放于ECX寄存器,函数自身清理堆栈;如果参数不确定,this指针在所有的参数入栈后再入栈,调用者清理栈。_thiscall不是关键字,程序员不能使用。参数按照从右至左的方式入栈。

参考:《逆向工程核心原理》——【韩】李承远