逆向基础(一)--- 函数调用协议汇总X86/X64/ARM/ARM64

本文中文字说明及图片所示的用例二进制文件下载链接:
二进制用例链接

X86 函数调用约定

函数调用协议会影响函数参数的入栈方式、栈内数据的清除方式、编译器函数名的修饰规则。如下图所示,可以在IDE环境中设定所有函数默认的调用协议,还可以在函数定义时单独设定本函数的调用协议。
逆向基础(一)--- 函数调用协议汇总X86/X64/ARM/ARM64_第1张图片

调用协议常用场合

  • __stdcall:Windows API默认的函数调用协议。
  • __cdecl:C/C++默认的函数调用协议。
  • __fastcall:适用于对性能要求较高的场合。

函数参数入栈方式

  • __stdcall:函数参数由右向左入栈。
    逆向基础(一)--- 函数调用协议汇总X86/X64/ARM/ARM64_第2张图片

  • __cdecl:函数参数由右向左入栈。
    逆向基础(一)--- 函数调用协议汇总X86/X64/ARM/ARM64_第3张图片

  • __fastcall:从左开始不大于4字节的参数放入CPU的ECX和EDX寄存器,其余参数从右向左入栈。
    逆向基础(一)--- 函数调用协议汇总X86/X64/ARM/ARM64_第4张图片

栈内数据清除方式

  • __stdcall:函数调用结束后由被调用函数清除栈内数据。
    逆向基础(一)--- 函数调用协议汇总X86/X64/ARM/ARM64_第5张图片
  • __cdecl:函数调用结束后由函数调用者清除栈内数据。
    逆向基础(一)--- 函数调用协议汇总X86/X64/ARM/ARM64_第6张图片
  • __fastcall:函数调用结束后由被调用函数清除栈内数据。
    参考图同__stndcall

C语言编译器函数名称修饰规则

“functionname”为函数名,“number”为参数字节数

  • __stdcall:编译后,函数名被修饰为“_functionname@number”。
  • __cdecl:编译后,函数名被修饰为“_functionname”。
  • __fastcall:编译后,函数名给修饰为“@functionname@nmuber”。

C++语言编译器函数名称修饰规则

“@@”+YG,YA,YI标识参数表的开始,后跟参数表
参数表以代号表示:
X–void ,
D–char,
E–unsigned char,
F–short,
H–int,
I–unsigned int,
J–long,
K–unsigned long,
M–float,
N–double,
_N–bool,

PA–表示指针,后面的代号表明指针类型,如果相同类型的指针连续出现,以“0”代替,一个“0”代表一次重复;

  • _stdcall:编译后,函数名被修饰“?functionname@@YG******@Z”。
    fastcall编译修饰
  • __cdecl:编译后,函数名被修饰为“?functionname@@YA******@Z”
    cdecl编译修饰
  • __fastcall:编译后,函数名被修饰为“?functionname@@YI******@Z”
    fastcall编译修饰

X64 函数调用约定

X64只有一种 fastcall 函数调用约定
参数1、参数2、参数3、参数4分别保存在 RCX、RDX、R8D、R9D ,剩下的参数从右往左依次入栈,被调用者实现栈平衡,返回值存放在 RAX 中。

vc调用的传参方式。前4个参数使用rcx,rdx,r8,r9,之后的参数使用堆栈。
GCC前6个参数使用rdi、rsi、rdx、rcx、r8、r9,剩下的参数用栈。注意rdx、rcx的顺序和MSVC上不一样。

ARM/ARM64 函数调用约定

ARM和ARM64使用的是ATPCS(ARM-Thumb Procedure Call Standard/ARM-Thumb过程调用标准)的函数调用约定。

ARM

参数1~参数4 分别保存到 R0~R3 寄存器中 ,剩下的参数从右往左依次入栈,被调用者实现栈平衡,返回值存放在 R0 中。
逆向基础(一)--- 函数调用协议汇总X86/X64/ARM/ARM64_第7张图片

ARM64

参数1~参数8 分别保存到 X0~X7 寄存器中 ,剩下的参数从右往左依次入栈,被调用者实现栈平衡,返回值存放在 X0 中。
逆向基础(一)--- 函数调用协议汇总X86/X64/ARM/ARM64_第8张图片

thiscall 函数调用约定

x86

参数从右往左依次入栈,this指针存放ECX中,被调用者实现栈平衡,返回值存放在 EAX 中。

X64

参数1、参数2、参数3分别保存在RDX、R8D、R9D中,this指针存放RCX中,剩下的参数从右往左依次入栈,被调用者实现栈平衡,返回值存放在 RAX 中。

ARM

参数1、参数2、参数3分别保存在R1、R2、R3中,this指针存放R0中,剩下的参数从右往左依次入栈,被调用者实现栈平衡,返回值存放在 R0 中。

ARM64

参数1~参数7 分别保存到 X1~X7 寄存器中,this指针存放X0中,剩下的参数从右往左依次入栈,被调用者实现栈平衡,返回值存放在 X0 中。

你可能感兴趣的:(逆向,编译器,安全,c++,linux)