函数堆栈图
进入函数之前EAX 0041C077 EBX 002FA000 ECX 0041C077 EDX 00000001 ESI 00411023 EDI 0019FEE8 EIP 004118B6 ESP 0019FE04 EBP 0019FEE8 EFL 0000024647:intmain(){00411890push ebp00411891mov ebp,esp00411893sub esp,0D8h00411899push ebx0041189A push esi0041189B push edi0041189C lea edi,[ebp-18h]0041189Fmov ecx,6004118A4 mov eax,0CCCCCCCCh004118A9 rep stos dword ptr es:[edi]004118AB mov ecx,41C077h004118B0 call00411325004118B5 nop48:intstart0;//断点在此处004118B6 mov dword ptr[ebp-8],049:func();004118BD call004112E9004118C2 nop50:intend0;004118C3 mov dword ptr[ebp-14h],051:return0;004118CA xor eax,eax52:}5:voidfunc(){00411820push ebp00411821mov ebp,esp00411823sub esp,0CCh00411829push ebx0041182A push esi0041182B push edi0041182C lea edi,[ebp-0Ch]0041182Fmov ecx,300411834mov eax,0CCCCCCCCh00411839rep stos dword ptr es:[edi]0041183B mov ecx,41C077h00411840call0041132500411845nop6:intnum0;00411846mov dword ptr[ebp-8],07:num;0041184D mov eax,dword ptr[ebp-8]00411850add eax,100411853mov dword ptr[ebp-8],eax8:return;9:}将断点下在 函数汇编的第一行00411820 push ebp执行到函数内部第一行汇编处 的 变化EAX 0041C077 EBX 002FA000 ECX 0041C077 EDX 00000001 ESI 00411023 EDI 0019FEE8 EIP 00411820 ESP 0019FE00 EBP 0019FEE8 EFL 00000246其中 变了的两个寄存器EIP 00411820 ESP 0019FE00原因在计算机架构与汇编语言中call指令在执行时主要产生以下两个核心效果保存返回地址将call指令下一条指令的地址即当前IP/EIP/RIP的值压入栈Stack中。这样做的目的是为了在子程序执行完毕后程序能够通过ret指令返回到调用处继续执行 [1, 2]。转移控制权将指令指针寄存器IP/EIP/RIP的内容修改为被调用子程序的入口地址。这会导致处理器跳转到目标代码段开始执行任务 [2, 3]。此时 ESP 的值变小了 说明栈被抬升了因为栈增长的方向是小地址ESP作为栈顶指针每次栈填充数据栈顶指针就要指向下一个位置位置的偏移量取决于填充的数据大小和可能的数据对齐此时ESP 减小的大小是4字节执行push ebp这个条指令只是把 ebp 的值 压入栈中并不修改ebp的值EAX 0041C077 EBX 002FA000 ECX 0041C077 EDX 00000001 ESI 00411023 EDI 0019FEE8 EIP 00411821 ESP 0019FDFC EBP 0019FEE8 EFL 00000246修改的寄存器是EIP 00411821 ESP 0019FDFC此时ESP 减小的大小是4字节因为 EBP是4字节大小的到目前为止没有改变EBP,现在考虑下EBP的值是什么EBP存储的是函数的栈底部相当于一个基准点 - 通过EBP可以访问函数的参数和局部变量- 每个函数都有自己的EBP值指向自己的栈帧开始位置在main函数中[ebp-8]访问局部变量start[ebp-14h]访问局部变量endEBP指向main的栈帧底部这种相对关系存在于 main 函数中也就是说我只需要获取到 EBP的值就可以获取到其他局部变量的值现在我在 func 函数中保存了 EBP的值所以实际上现在 在 func 中是可以通过 EBP 的值去访问 main中存储的局部变量的执行 mov ebp,espEAX 0041C077 EBX 00352000 ECX 0041C077 EDX 00000001 ESI 00411023 EDI 0019FEE8 EIP 00411823 ESP 0019FDFC EBP 0019FDFC EFL 00000246变化的寄存器是EIP 00411823 EBP 0019FDFC现在开始真正改变 EBP了EBP的值如果被改变了那当函数结束后之前 局部变量再通过之前 和 EBP的关系 不就定位不到了吗其实不用关心上一步已经保存了 上一个函数 的EBP, 当这个函数将要结束时会取出保存的EBP这里修改EBP,而且将 EBP 指向和ESP指向的同一块位置 现在EBP ESP都位于 上一个函数的栈帧的顶部ESP指向的是栈顶而不是 栈顶的下一个位置 把 ESP 想象成**书堆的顶部** - 你放一本新书时先把手指移到新位置ESP移动然后放书写入数据 - 你的手指总是指向最上面的那本书最后一个有效数据 - 不是指向书上面的空气下一个空闲位置执行 sub esp,0CChEAX 0041C077 EBX 0027A000 ECX 0041C077 EDX 00000001 ESI 00411023 EDI 0019FEE8 EIP 00411829 ESP 0019FD30 EBP 0019FDFC EFL 00000206改变的寄存器是EIP 00411829 ESP 0019FD30 EFL 00000206为什么mov ebp,esp 之后是 sub esp,0CCh 现在不是ebp指向了和esp相同的位置了吗按道理说只需要push push 就可以抬升 esp,为什么使用sub操作抬升原因是使用sub esp, N一次性分配所有局部变量空间比用多个push指令更高效1.效率考量sub esp, 0CCh1条指令分配 204 字节用push需要约 51 条push指令204÷4节省指令数执行更快2.访问方式不同用push分配的局部变量assemblypush 0 ; [esp] 是变量1push 0 ; [esp] 是变量2[esp4] 是变量1push 0 ; [esp] 是变量3[esp4] 是变量2[esp8] 是变量1问题ESP 一直在变访问局部变量时偏移计算复杂用sub esp, N分配assemblysub esp, 12 ; 分配12字节mov [ebp-4], 0 ; 局部变量1mov [ebp-8], 0 ; 局部变量2mov [ebp-12], 0 ; 局部变量3优势EBP 固定通过固定偏移访问局部变量执行保存易变寄存器00411829 push ebx 0041182A push esi 0041182B push ediEAX 0041C077 EBX 0027A000 ECX 0041C077 EDX 00000001 ESI 00411023 EDI 0019FEE8 EIP 0041182C ESP 0019FD24 EBP 0019FDFC EFL 00000206变化的寄存器是EIP 0041182A ESP 0019FD2C EIP 0041182B ESP 0019FD28 EIP 0041182C ESP 0019FD24执行 lea edi,[ebp-0Ch]EAX 0041C077 EBX 0027A000 ECX 0041C077 EDX 00000001 ESI 00411023 EDI 0019FDF0 EIP 0041182F ESP 0019FD24 EBP 0019FDFC EFL 00000206变化的寄存器是EDI 0019FDF0 EIP 0041182F执行 mov ecx,3EAX 0041C077 EBX 0027A000 ECX 00000003 EDX 00000001 ESI 00411023 EDI 0019FDF0 EIP 00411834 ESP 0019FD24 EBP 0019FDFC EFL 00000206变化的寄存器是ECX 00000003 EIP 00411834执行 mov eax,0CCCCCCCChEAX CCCCCCCC EBX 0027A000 ECX 00000003 EDX 00000001 ESI 00411023 EDI 0019FDF0 EIP 00411839 ESP 0019FD24 EBP 0019FDFC EFL 00000206变化的寄存器是EAX CCCCCCCC EIP 00411839执行 rep stos dword ptr es:[edi]EAXCCCCCCCC EBX0027A000 ECX00000000EDX00000001ESI00411023EDI0019FDFC EIP0041183B ESP0019FD24 EBP0019FDFC EFL00000206变化的寄存器是ECX 00000000 EDI 0019FDFC EIP 0041183BSTOSStore String是x86汇编中的字符串存储指令用于将累加器AL/AX/EAX的值存储到内存中综合上述的 mov eax,0CCCCCCCCh 和 mov ecx,3 和 lea edi,[ebp-0Ch]可知是以 ebp为基点向上抬升3个字节大小0ch是12同时指定循环次数是3次同时向 edi 指向的 处开始填充数据 0CCCCCCCCh每次填充数据会自动移动填充数据的指向指针执行安全检查函数0041183B mov ecx,41C077h ; 将安全 Cookie 值加载到 ECX 00411840 call 00411325 ; 调用 __security_check_cookie 函数 00411845 nop ; 对齐填充无操作这是 Windows 程序的栈溢出保护机制工作原理函数开始时在栈帧中插入一个随机值Cookie函数结束时检查这个值是否被改变如果被改变说明发生了栈溢出程序立即终止执行 mov dword ptr [ebp-8],0使用ebp作为基点在一个字节的偏移处设置数据为 0执行自增操作0041184D mov eax,dword ptr [ebp-8] 00411850 add eax,1 00411853 mov dword ptr [ebp-8],eax将局部变量存储到 临时寄存器对寄存器自增将自增的值放回局部变量执行恢复易变寄存器00411856 pop edi 00411857 pop esi 00411858 pop ebx还原 Esp到 ebp的初始位置add esp,0CCh注意从 执行 mov ebp,esp 不包括这个指令 到现在 ebp作为基础点都没有修改过验证ESP 是否真的还原成功cmp ebp,esp现在如果正确执行的话 EBP 和 ESP 都是指向同一个位置的验证ESP的值是否有效call 00411244打开显示符号名00411861 call __RTC_CheckEsp (0411244h)执行一个看起来没什么用的指令mov esp,ebp因为 esp 和ebp 在之前都指向同一个位置了执行 pop ebppop指令负责从栈中取出一个元素并使得 esp 4,栈的高度下降同时 这里是放到ebp中此时的寄存器的值是EAX 00000001 EBX 0027A000 ECX 0041C077 EDX 00000001 ESI 00411023 EDI 0019FEE8 EIP 00411869 ESP 0019FE00 EBP 0019FEE8 EFL 00000246刚好和 执行完执行 push ebp 保存 ebp 时 EBP 寄存器的数据相同此时堆栈平衡现在的EBP的值就是上一个函数的EBP的值了

相关新闻

提示词翻译润色模板已迭代至V4.2:实测降低LLM输出歧义率82%,附3分钟自检清单(失效即删)

提示词翻译润色模板已迭代至V4.2:实测降低LLM输出歧义率82%,附3分钟自检清单(失效即删)

更多请点击: https://intelliparadigm.com 第一章:提示词翻译润色模板已迭代至V4.2:实测降低LLM输出歧义率82%,附3分钟自检清单(失效即删) V4.2版本核心升级聚焦语义锚定与上下文隔离机制,通过…

2026/10/15 18:29:54 阅读更多 →
PDF视觉差异检测终极指南:diff-pdf工具深度解析

PDF视觉差异检测终极指南:diff-pdf工具深度解析

PDF视觉差异检测终极指南:diff-pdf工具深度解析 【免费下载链接】diff-pdf A simple tool for visually comparing two PDF files 项目地址: https://gitcode.com/gh_mirrors/di/diff-pdf 在文档管理和版本控制工作中,PDF文件的差异检测常常令人头…

2026/9/26 15:53:55 阅读更多 →
深入解析DRA78x汽车信息娱乐处理器:异构计算、车规级与音频处理核心

深入解析DRA78x汽车信息娱乐处理器:异构计算、车规级与音频处理核心

1. 项目概述:深入解析DRA78x汽车信息娱乐处理器的核心价值在当今的汽车座舱里,那块中控大屏早已不是简单的收音机和CD播放器,它已经演变成一个集成了导航、影音娱乐、车辆状态监控、手机互联乃至部分驾驶辅助功能的综合信息中枢。这个复杂系统…

2026/10/7 8:27:59 阅读更多 →

最新新闻

Java实现微信企业付款到零钱(v3接口)实战指南

Java实现微信企业付款到零钱(v3接口)实战指南

简介:本资源是一份面向Java后端开发者的企业级微信支付实战代码包,聚焦微信企业付款到零钱核心功能,适用于工资发放、奖金结算、退款处理等真实业务场景。资源共2个Java源文件,总大小仅3KB,轻量精炼:其中Wx…

2026/10/15 18:29:44 阅读更多 →
CEF拦截WSS全攻略:在握手前阻断WebSocket Secure连接

CEF拦截WSS全攻略:在握手前阻断WebSocket Secure连接

简介:面向.NET开发者的一套CEFSharp完整拦截方案代码,目标是让应用程序接管浏览器内全部WSS与WebSocket通信,适合需要调试实时数据、实施安全审计或做自定义过滤的中高级开发人员。资源以WinForm项目为载体,覆盖从注册自定义Schem…

2026/10/15 18:29:44 阅读更多 →
Nessus授权扫描实战:从部署策略到报告解读的完整指南

Nessus授权扫描实战:从部署策略到报告解读的完整指南

搞安全这行,漏洞扫描是绕不开的日常。不管你是企业安全团队的在编人员,还是乙方评估机构的外派工程师,刚接触安全评估的工具清单里,Nessus几乎都是第一个跳出来的名字——插件库更新快,上手门槛低,报告的误…

2026/10/15 18:29:44 阅读更多 →
轻量级txt转XML工具:工业场景下的结构化数据转换实践

轻量级txt转XML工具:工业场景下的结构化数据转换实践

简介:这是一款面向编程初学者与数据处理开发者的轻量级TXT转XML格式转换工具,解决非结构化文本数据难以直接用于系统集成、配置管理或API交互的痛点,适用于教学实践、小规模数据迁移及XML入门学习场景。资源包共37个文件,以12个C#…

2026/10/15 18:29:44 阅读更多 →
Flutter for OpenHarmony状态管理实战:从选型到跨端同步排坑

Flutter for OpenHarmony状态管理实战:从选型到跨端同步排坑

在 Flutter 跨平台这件事上,Android、iOS 甚至 Windows 都已经是老生常谈了,但如果是把 Flutter 跑在 OpenHarmony 上呢?这事的关注度这几年一直在涨。尤其当你手里正好有一台搭载 OpenHarmony 的设备,又不想为了这套系统单独维护…

2026/10/15 18:29:44 阅读更多 →
如何安全取消 wreq 请求?深入 HTTP/1、HTTP/2、HTTP/3 的 Cancel Safety 完整指南

如何安全取消 wreq 请求?深入 HTTP/1、HTTP/2、HTTP/3 的 Cancel Safety 完整指南

【免费下载链接】wreq An ergonomic, privacy-aware Rust HTTP Client 项目地址: https://gitcode.com/gh_mirrors/rq/wreq 点击查看 免费下载 wreq 是一个注重易用性与隐私的 Rust 异步 HTTP 客户端。在 wreq 中取消请求的方式非常统一:丢弃&#xff0…

2026/10/15 18:28:43 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/15 16:18:54 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/15 13:48:15 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 9:49:14 阅读更多 →