函数调用约定
__cdecl 调用方式
__stdcall 调用方式
__fastcall 调用方式
函数调用栈帧分析
补充说明
- 不同的编译器实现不一样,上述情况只是VC++6.0的编译实现
- 即便是在同一个编译器,开启优化和关闭优化也不一样
- 即便是同一个编译器同一种模式,32位和64位下情况也会不一样
fastcall 实例分析
[[gnu::fastcall]] int fun1(int a, int b, int c, int d) {
return a * a + b * b + 2 * a * b + c + d;
}
int main() {
int c = fun1(3, 4, 5, 6);
return 0;
}
#!/bin/bash
set -ex
/mnt/e/code/llvm-project/build/bin/clang fastcallTest.c -o fastcallTest -O0 -g -m32 -c
# 编译生成汇编代码
objdump -dS fastcallTest &> fastcallTest.asm
# sudo apt-get install -y build-essential module-assistant
# sudo apt-get install -y gcc-multilib g++-multilib
参考 GCC GNU 文档属性描述
fastcall
On x86-32 targets, the fastcall attribute causes the compiler to pass the first argument (if of integral type) in the register ECX and the second argument (if of integral type) in the register EDX. Subsequent and other typed arguments are passed on the stack. The called function pops the arguments off the stack. If the number of arguments is variable all arguments are pushed on the stack.
翻译: 在 x86-32 目标机上,fastcall 属性会导致编译器在寄存器 ECX 中传递第一个参数(如果是 INT 类型),在寄存器 EDX 中传递第二个参数(如果是INT类型)。后面的参数和其他类型的参数会传递到堆栈中。被调用函数将参数从堆栈中弹出。如果参数个数不固定,所有参数都会被推入堆栈。