从汇编代码探究函数栈帧的创建和销毁的底层原理(一)

简介: 从汇编代码探究函数栈帧的创建和销毁的底层原理

一、先导知识

C/C++中内存分为3个区域:栈区、堆区、静态区

不同性质的变量存放在不同的内存区域中,下图是各种变量所在内存中的区域
本文所讲的函数栈帧的创建和销毁过程就是在栈区进行的


栈区存放变量的特点:先存高地址,再存低地址。


销毁变量的时候是先销毁低地址里面的变量,再销毁高地址里面的变量,如图


例如:变量1先创建,再创建变量2......创建变量8;但是销毁的时候,就是先销毁变量8......最后销毁变量1

本文中将用到的两个寄存器:ebp、esp,这两个指针中存放的是地址,用来维护函数栈帧

ebp是栈底指针、esp是栈顶指针正在调用哪个函数,ebp、esp就维护哪个函数的函数栈帧

二、函数调用堆栈

在vs2013中来测试并观察main函数栈帧的创建过程

F10-->调试-->窗口-->调用堆栈  一直按F10直到程序结束,就会出现下面的场景

可以看到main函数是由626行的那个函数 __tmainCRTStartup函数调用的
而  __tmainCRTStartup 函数又是由466行的   mainCRTStartup 函数调用的,调用的顺序正是由栈顶往栈底

三、函数栈帧的创建

1.创建函数栈帧

有(二)中可知,VS2013中,main函数也是被其他函数调用的,每一次函数调用都要在栈区上分配空间,接下来就通过观察汇编代码来看观看函数栈帧的创建,假设mian函数中还有一个Add函数,来计算两个数的相加的和。按下F10后不要乱动,右击鼠标,转到反汇编(C语言对应的汇编代码)

这就是这段代码对应的汇编代码

由于main函数是由 __tmainCRTStartup函数调用的,所以在调用main函数前,main函数的函数栈帧已经创建好了

push:给栈顶放一个元素

push          ebp 将ebp里面的值放在栈顶,同时因为esp指向的是栈顶,所以esp指针也‘上移’

如图

mov:将前面的值放到后面值的地方

mov        ebp,esp,将ebp指针移动到esp指针的位置

sub:前面的值减去后面的值

sub         esp,0E4h,指针esp减去0E4h(一个8进制的数字),并移动指针esp

由于ebp是栈底指针,esp是栈顶指针,正在调用哪个函数,ebp和esp就维护哪个函数的函数栈帧

后面调用Add函数的时候,ebp、esp就去维护Add函数的函数栈帧。

所以栈区中mian函数的调用空间(预开辟)就开辟好了连续push三次,将这三个元素依次放到栈顶,压栈三次

同时esp也移动到栈顶

lea:load effecitive address   加载有效地址

lea             edi,[ebp-0E4h]  把  ebp-0E4h 的地址放到edi里面去,而ebp-0E4h应该就是main函数的栈顶地址


mov           ecx,39h 把39h的值放入eax中去


mov           eax,0CCCCCCCCh 把0CCCCCCCCh的值放入eax中


rep stos     dword ptr es:[edi] 把从 edi(edp-0E4h)开始向下ecx(39h)次 dword 的数据全部都改成 eax(0CCCCCCCC) (dword(双字节))图例


简单的来讲就要将从 edp-0E4h 到 ebp 中间所有的内容初始化为0ECCCCCCCC

假设初始化完了(没有画全),意思就是中间全部初始化为0CCCCCCCC此时main函数才开始执行代码


相关文章
|
2月前
|
网络协议 C++
解决MASM32代码汇编出错: error A2181: initializer must be a string or single item
解决MASM32代码汇编出错: error A2181: initializer must be a string or single item
|
3月前
|
存储 算法 程序员
神秘代码世界惊现高效秘籍!究竟是什么让汇编语言编程如此强大?快来一探究竟!
【8月更文挑战第31天】《代码之美:探索高效汇编语言编程的最佳实践》介绍了汇编语言在系统内核、嵌入式系统及高性能应用中的不可替代作用。书中强调了深入理解处理器架构、提升代码可读性、优化算法与数据结构及有效利用寄存器等最佳实践的重要性。通过具体示例,如在 x86 架构下实现高效的加法函数,展示了如何运用这些技巧编写出既高效又可靠的汇编代码,充分展现了汇编语言的独特魅力及其在现代软件开发中的价值。
45 0
|
2月前
|
Windows
【原创】DOS下TSR程序的汇编演示代码2--黑屏保护程序
【原创】DOS下TSR程序的汇编演示代码2--黑屏保护程序
【原创】DOS下TSR程序的汇编演示代码1--自动按键程序
【原创】DOS下TSR程序的汇编演示代码1--自动按键程序
|
3月前
|
NoSQL 前端开发 程序员
【震撼揭秘!】程序员绝不会告诉你的秘密:掌握汇编语言调试,轻松从软件故障中全身而退——透视代码底层,成为Bug猎人!
【8月更文挑战第31天】《调试的艺术:如何利用汇编语言追踪和解决软件问题》探讨了使用汇编语言进行高效调试的方法。无论是初学者还是资深开发者,面对棘手的 bug 时,高级语言的信息往往不足。文章通过具体示例展示如何通过汇编代码定位问题,如 C 语言中数组求和函数的崩溃问题。借助 `gcc -S` 生成的汇编代码和 GDB 调试器,可以深入理解程序行为,从而更准确地解决问题。掌握这一技能,将使你在复杂问题面前更加从容。
42 2
|
3月前
|
C语言
51单片机汇编语言流水灯代码
51单片机汇编语言流水灯代码
|
3月前
|
C# 开发者 图形学
Xamarin 竟在游戏开发领域大胆探索,跨平台优势与强大功能结合,开启游戏开发新潮流!
【8月更文挑战第31天】《Xamarin在游戏开发领域的探索》介绍了Xamarin作为跨平台开发框架,在移动游戏开发中的应用。它利用C#语言的优势,提供高效的开发体验,并结合各平台图形库实现高质量画面。本文还展示了Xamarin如何简化游戏逻辑处理、支持多线程编程及与Unity等工具集成,提升游戏质量和开发效率。此外,Xamarin还支持热更新和多平台发布,进一步优化游戏维护流程。
43 0
|
6月前
|
存储 Unix 编译器
汇编语言----X86汇编指令
汇编语言----X86汇编指令
222 2
|
1月前
|
存储 移动开发 C语言
【ARM汇编速成】零基础入门汇编语言之指令集(三)
【ARM汇编速成】零基础入门汇编语言之指令集(三)
|
1月前
|
编译器 C语言 计算机视觉
【ARM汇编速成】零基础入门汇编语言之指令集(二)
【ARM汇编速成】零基础入门汇编语言之指令集(二)
137 0