### 函数的调用约定有哪些，区别是什么

**1. `cdecl` (C Declaration)**

这是 C 语言的默认调用约定，也是最常见的

- **参数传递**：从**右到左**依次推入栈中
- **栈清理**：由**调用方（caller）**负责在函数返回后清理栈
- **寄存器**：`eax`, `ecx`, `edx` 是调用方保存的（caller-saved）寄存器。这意味着被调用函数可以自由使用这些寄存器，如果调用方需要保存它们，需要在调用前自己推入栈中

**优点**：支持可变参数函数，例如 `printf`

**缺点**：每次函数调用后都需要调用方执行额外的栈清理指令，会增加代码大小

**2. `stdcall` (Standard Call)**

这是 Windows API 的默认调用约定

- **参数传递**：从**右到左**依次推入栈中
- **栈清理**：由**被调用方（callee）**负责清理栈
- **寄存器**：与 `cdecl` 类似

**优点**：代码更精简。由于被调用方知道参数数量，只需一条指令即可清理栈

 **缺点**：不支持可变参数函数，因为被调用方需要知道参数数量才能正确清理栈

**3. `fastcall`**

这是一个为了提高性能而设计的调用约定

- **参数传递**：前两个（或更多，具体取决于编译器和架构）参数通过**寄存器**传递，而不是通过栈。其余参数从右到左推入栈中
- **栈清理**：由**被调用方**清理栈
- **寄存器**：使用 `ecx` 和 `edx`（在 32 位 Windows 上）或 `rcx` 和 `rdx`（在 64 位 Windows 上）来传递前两个参数

**优点**：通过减少内存访问（栈操作）来提高函数调用速度

 **缺点**：不支持可变参数函数

**4. `thiscall`**

这是 C++ 中非静态成员函数的默认调用约定

- **参数传递**：与 `cdecl` 或 `stdcall` 类似，但隐藏的 `this` 指针（指向对象实例）通过**寄存器**传递
- **栈清理**：由**被调用方**清理栈

**优点**：优化了 C++ 成员函数的调用

 **缺点**：只能用于 C++ 成员函数

**5. `pascal` (Pascal Language)**

在老旧的 Windows 16 位编程中很常见，现在很少使用

- **参数传递**：从**左到右**推入栈中
- **栈清理**：由**被调用方**清理栈

**不同平台下的调用约定**

- **Windows (x86)**：
  - `cdecl`：C/C++ 默认
  - `stdcall`：Windows API 默认
  - `fastcall`：用于性能优化
  - `thiscall`：C++ 成员函数
- **Windows (x64)**：
  - `__fastcall`：这是 64 位 Windows 的唯一调用约定。前四个整数或指针参数通过 `rcx`, `rdx`, `r8`, `r9` 寄存器传递。其余参数从右到左推入栈中
- **Linux (x86)**：
  - `cdecl`：默认
- **Linux (x64)**：
  - 前六个整数或指针参数通过 `rdi`, `rsi`, `rdx`, `rcx`, `r8`, `r9` 寄存器传递。其余参数从右到左推入栈中