前置知识: C

函数调用栈帧

1 minAdvanced2026/6/14

C语言函数调用栈帧详解:局部变量、返回地址、寄存器保存。

1. 栈帧结构

高地址
┌─────────────────┐
│   参数 n         │
│   ...            │
│   参数 1         │
│   返回地址        │ ← 调用前的栈顶
├─────────────────┤
│   保存的 EBP     │ ← 当前 EBP
├─────────────────┤
│   局部变量 1     │
│   局部变量 2     │
│   ...            │
├─────────────────┤
│   临时空间       │ ← ESP
└─────────────────┘
低地址

2. 调用过程

; 调用前
push arg2        ; 参数从右到左入栈
push arg1
call func        ; push 返回地址,jmp func

; func 入口
push ebp         ; 保存旧 EBP
mov ebp, esp     ; 设置新 EBP
sub esp, N       ; 分配局部变量空间

; func 退出
mov esp, ebp     ; 释放局部变量
pop ebp          ; 恢复 EBP
ret              ; pop 返回地址,jmp 回去

3. 调用约定

约定参数传递栈清理名称修饰
cdecl从右到左入栈调用者_func
stdcall从右到左入栈被调用者_func@N
fastcallECX, EDX + 栈被调用者@func@N

4. 栈溢出

void recursive() {
    char buffer[1024]; // 每次分配 1KB
    recursive();       // 无限递归 → 栈溢出
}

栈大小通常为 1-8MB,超出即崩溃。