汇编——堆栈平衡

基础定义

栈由操作系统为进程预先分配,承担函数参数传递、保存返回地址、存放局部临时数据、寄存器现场等工作

堆栈平衡:调用函数前与函数完全执行完毕后,ESP 栈指针数值必须一模一样,栈整体状态完全还原

核心要求:函数内部临时增减 ESP 没关系,但 RET 返回前必须抵消掉参数压栈带来的 ESP 偏移;失衡会栈错乱、数据读取错误、程序崩溃

失衡危害

调用前 push 了若干参数,函数返回后 ESP 没有复原:

1.后续栈读写拿到错误内存数据

2.多层函数嵌套调用时,返回地址错位,EIP 跳飞

3.严重直接程序异常崩溃

标准准则:调用点执行 call 前后 ESP 数值相等

两种堆栈平衡方案(外平衡、内平衡)

外平衡(调用方平衡,对应 C 语言 cdecl 约定)

平衡代码写在call 指令之后、函数外部

原理:调用端 push 参数,函数 ret 单纯只弹出返回地址,外部手动 add esp 回收参数占用空间

示例

cpp 复制代码
;调用端
push 10
push 20
call MyFunc
add esp,8   ;外平衡:外部修正ESP,回收两个参数8字节空间

;函数内部
MyFunc:
mov eax,[esp+4]
add eax,[esp+8]
ret         ;只弹出返回地址,不处理参数

内平衡(被调函数内部平衡,stdcall 约定)

平衡逻辑放在函数内部,依靠ret n指令实现

ret n动作:弹出返回地址给 EIP 后,自动执行 ESP = ESP + n,一次性清空 n 字节参数空间

示例

cpp 复制代码
;调用端只负责压参、调用,无后续平衡代码
push 10
push 20
call MyFunc

;函数内部内平衡
MyFunc:
mov eax,[esp+4]
add eax,[esp+8]
ret 8       ;内平衡:弹返回地址 + ESP+=8,清理两个参数

执行流程对比

外平衡流程: push 参数 → call 压返回地址 → 函数运算 → ret 回到 call 下一行 → 外部 add esp 修正栈

内平衡流程: push 参数 → call 压返回地址 → 函数运算 → ret n 一步完成返回 + 栈平衡,调用端无需额外代码

细节

1.函数内部开栈(sub esp 分配局部变量)、push 保存寄存器,只要在 ret 前原样 pop 恢复寄存器、恢复 ESP,不影响整体堆栈平衡

2.返回值统一存 EAX,平衡操作不改变 EAX 结果

3.平衡数值计算:参数个数×4 字节(32 位)

约定 平衡方式 返回指令 可变参数

cdecl 调用方外平衡 ret 支持

stdcall 函数内平衡 ret n 不支持

相关推荐
AI情绪识别开源12 小时前
检信 ALLEMOTION OS 加密打包可执行程序 — 全面测试报告版本: v1.3功能测试 / 性能测试 /
开发语言·数据结构·人工智能·功能测试
「QT(C++)开发工程师」13 小时前
C++ auto 用法详解
开发语言·c++
OPEN-F13 小时前
C++STL教程:容器适配器与实用工具
开发语言·c++
yaoxin52112313 小时前
507. Java 反射 - 在 BeanFactory 中实现依赖注入
java·开发语言
OPEN-F13 小时前
C++模板教程:变参模板、折叠表达式与SFINAE
java·开发语言·c++
有点。13 小时前
C++二叉搜索树进阶
开发语言·c++
HugoStudio_SWAN13 小时前
【擦除重绘】C++ 控制台动画:弹跳 Logo DVD 屏保效果
开发语言·c++·学习·程序人生
kyle~15 小时前
C++_STL---迭代器失效
开发语言·c++
Brilliantwxx16 小时前
【C语言】 初入嵌入式C语言复习(基础+进阶面试题)
c语言·开发语言