汇编——寻址方式

ESP寻址

ESP 寻址定义

ESP 寻址是以栈指针ESP作为基准地址,搭配固定偏移量 ESP+数值 读写栈内参数、临时数据的寻址方式,是堆栈传参函数读取入参的核心手段

学习前提:掌握寄存器传参、堆栈压参调用逻辑

两种传参对照铺垫

  1. 寄存器传参(少参数)
    参数直接放进通用寄存器,无需栈、不用 ESP 寻址读参
cpp 复制代码
;调用
mov ecx,10
mov edx,20
call AddReg
;函数
AddReg:
mov eax,ecx
add eax,edx
ret
  1. 堆栈传参(多参数标配)
    调用方 push 压参数,函数内部依靠 ESP 偏移取值,也就是 ESP 寻址
cpp 复制代码
push 20
push 10
call AddStack
add esp,8 ;外平衡

ESP 寻址底层原理

执行 call 瞬间,栈布局固定:

ESP:call 自动压入的返回地址(占 4 字节)

ESP+4:第一个压入的参数

ESP+8:第二个压入的参数 每多一个参数,偏移额外 + 4

函数内部取值示例:

cpp 复制代码
AddStack:
mov eax,[esp+4]   ;ESP寻址取参数1
add eax,[esp+8]   ;ESP寻址取参数2
ret

配套堆栈平衡规则

平衡标准:call 执行前 和 call 结束后 ESP 数值完全一致

外平衡 (cdecl):函数只用普通 ret,call 后add esp,总参数字节

内平衡 (stdcall):函数结尾ret n,自动弹返回地址 + 抬高 ESP 清理参数 失衡后果:栈地址错乱、返回地址读取错误、程序崩溃

ESP 寻址优缺点

优点

1.写法简单,仅用 ESP 加固定偏移就能读取所有栈参数

2.无需额外基址寄存器,节省 EBX/EBP 等通用寄存器

缺点

1.ESP 是动态变化的:函数内 push 寄存器、sub esp 开局部变量都会改变 ESP 值,偏移量跟着变大,计算繁琐

2.复杂多层逻辑、大量局部变量时,偏移极易算错,读错参数

3.若中途频繁改动 ESP,必须手动重新换算偏移,稳定性差

EBP寻址

EBP 寻址核心优势

1.EBP 是栈基址(栈底指针),专门用作稳定寻址基准

2.ESP 会因为 push、sub esp、局部变量分配持续变动,EBP 一经初始化全程固定不变

3.偏移值EBP±数值从头到尾统一,不会因为栈操作改来改去,大幅降低寻址计算失误

EBP 标准初始化流程(函数固定开头序言 prolog)

1.push ebp:把上层函数原来的 EBP 压栈保存,防止覆盖丢失

2.mov ebp, esp:让 EBP 定格在进入函数那一刻的 ESP 位置,锁定基准

3.sub esp, N:抬高 ESP,向下开辟 N 字节栈空间,存放局部变量

执行完这三步,EBP 数值永久固定,不管后面怎么 push、读写栈,基准不动

栈布局(EBP 锁定后)

以 2 个栈传参举例:

内存位置 存放内容
EBP+0 保存的上层旧 EBP
EBP+4 CALL 压入的返回地址
EBP+8 第一个传入参数
EBP+12 第二个传入参数
EBP-4EBP-8 ...... 函数内部局部变量

加法函数代码演示(EBP 寻址)

cpp 复制代码
;调用端 cdecl外平衡
push 20
push 10
call AddEbp
add esp,8

;函数主体
AddEbp:
push ebp            ;1.保存旧ebp
mov ebp,esp         ;2.ebp锁定当前esp基准
sub esp,0x8         ;3.开辟8字节局部变量空间

mov eax,[ebp+8]     ;取参数1=10
mov [ebp-4],eax     ;存入局部变量1
mov eax,[ebp+12]    ;取参数2=20
mov [ebp-8],eax     ;存入局部变量2

mov eax,[ebp-4]
add eax,[ebp-8]     ;求和,结果放eax

;函数收尾epilog,恢复栈平衡
mov esp,ebp         ;把esp还原回ebp基准,清空局部变量空间
pop ebp             ;弹出上层旧ebp,恢复
ret                 ;返回,外部平衡栈

EBP 寻址配套栈平衡收尾(epilog 尾声)

固定恢复步骤:

1.mov esp, ebp:直接把 ESP 拉回 EBP 的基准位置,一次性释放所有 sub esp 开辟的局部栈空间,不用逐次加减修正

2.pop ebp:还原调用方原本的 EBP 值

3.ret / ret n 完成返回

平衡作用

1.一键抹平函数内部所有局部变量、临时 push 带来的 ESP 变动

2.保证退出函数时栈状态和进入时匹配,杜绝寻址错乱、栈失衡崩溃

3.对比纯 ESP 寻址:复杂多层代码、多局部变量场景下,EBP 偏移全程稳定,几乎不会算错偏移量

对比 ESP 与 EBP 寻址

ESP:基准动态变化,每一次栈操作都要重算偏移,简单小函数能用,复杂函数极易出错

EBP:基准永久固定,参数、局部变量偏移全程不变,是编译器 C/C++ 函数默认标准栈寻址方案

相关推荐
菩提小狗6 小时前
每日安全情报报告 · 2026-09-01
网络安全·漏洞·cve·安全情报·每日安全
OPEN-F6 小时前
C++并发编程:条件变量与原子操作
java·开发语言·c++
神仙别闹7 小时前
基于 C++实现(控制台)车辆信息管理系统
开发语言·c++
智塑未来7 小时前
常用的在线ping测试工具有哪些
服务器·开发语言·php
Freak嵌入式7 小时前
MicroPython+Pico 接收空闲中断和发送空闲中断全实战
java·开发语言·stm32·单片机·嵌入式硬件
重生之小比特7 小时前
【初阶C++】string
开发语言·c++
小玮看世界7 小时前
[Python]动态规划三步走:从爬楼梯到打家劫舍,再到最大子数组和
开发语言·python·动态规划
AI视觉网奇8 小时前
3d子部件高亮选中
开发语言·javascript·3d
zzzll11118 小时前
深入理解 Java HashMap:从原理到实战
java·开发语言·哈希算法
Seraphina368 小时前
记一次实验:利用缓存服务器规范化技术进行网页缓存欺骗
经验分享·笔记·网络安全·缓存