【深入理解函数栈帧:探索函数调用的内部机制】

news/2024/12/5 6:42:33/

本章我们要介绍的不是数学中的函数,而是C语言中的函数哟!

本章重点

  • 了解汇编指令
  • 深刻理解函数调用过程

样例代码:

#include <stdio.h>
int MyAdd(int a, int b)
{int c = 0;c = a + b;return c;
}int main()
{int x = 0xA;int y = 0xB;int z = MyAdd(x, y);printf("z = %x\n", z);return 0;
}

C语言地址空间学习

  • 代码段:存储程序的机器指令,包括函数的二进制代码。
  • 字符常量区:存储字符串常量和字符常量,这些值在程序中是只读的,不可修改。
  • 已初始化变量区:存储已经初始化的全局变量和静态变量。
  • 未初始化变量区:存储未初始化的全局变量和静态变量,在程序加载时会被初始化为默认值(如0)。
  • 堆:动态分配的内存区域,用于存储动态分配的变量、数据结构和对象。它的大小和位置在程序运行时动态调整。
  • 栈:存储函数调用的局部变量、函数参数、函数返回地址以及其他与函数调用相关的信息。栈是一种后进先出(LIFO)的数据结构,函数调用时会在栈上创建一个新的帧,函数返回时会将该帧从栈中弹出。

认识相关寄存器

  • eax:通用寄存器,保留临时数据,常用于返回值

  • ebx:通用寄存器,保留临时数据

  • ebp:栈底寄存器 esp:栈顶寄存器

  • eip:指令寄存器,保存当前指令的下一条指令的地址

认识相关汇编命令

  • mov:数据转移指令

  • push:数据入栈,同时esp栈顶寄存器也要发生改变

  • pop:数据弹出至指定位置,同时esp栈顶寄存器也要发生改变

  • sub:减法命令

  • add:加法命令

  • call:函数调用,1. 压入返回地址 2. 转入目标函数

  • jump:通过修改eip,转入目标函数,进行调用

  • ret:恢复返回地址,压入eip,类似pop eip命令

讲解思路图

备注: vs编译器有栈随机化的处理,所以每次看到的相关数据可能会不太一致,不过我们重点关注变化原理,弱化数据。

1、起步,main函数也是要被调用的

2、main函数也是要形成栈帧结构的

3、变量x和入栈

4、临时变量的入栈拷贝

6、开始调用函数

7、MyAdd函数栈帧形成

8、变量c入栈并完成加法

9、寄存器eax保存返回值

10、释放MyAdd函数栈帧

11、ret返回

12、函数参数的临时变量被销毁, 程序已经回到main函数栈帧,并且已经将寄存器eax的值给到z变量。

总结:

  1. 调用函数,需要先形成临时拷贝,形成过程是从右向左的
  2. 临时空间的开辟,是在对应函数栈帧内部开辟的
  3. 函数调用完毕,栈帧结构被释放掉
  4. 临时变量具有临时性的本质:栈帧具有临时性
  5. 调用函数是有成本的,成本体现在时间和空间上,本质是形成和释放栈帧有成本
  6. 函数调用,因拷贝所形成的临时变量,变量和变量之间的位置关系是有规律的

根据第六点,我们可以发现一个现象

#include <stdio.h>
void MyAdd(int a, int b)
{//由于临时变量是从右往左创建的//所以b的地址高于aprintf("before:%d\n", b);*(&a + 1) = 100;printf("after:%d\n", b);
}int main()
{int x = 0xA;int y = 0xB;MyAdd(x, y);return 0;
}

我们上面的代码能很好的体现函数参数的地址位置关系,但这是一种不可预测和不可靠的行为。

  1. 临时变量的内存布局是由编译器决定的,这是未定义行为。不同的编译器可能采用不同的策略和规则来分配内存。因此,不能依赖于特定的内存布局来进行编程。

  2. 临时变量在栈上分配内存,通常是从高地址向低地址分配。因此,b的地址可能比a的地址更高。然而,这并不意味着b的地址正好位于a的下一个内存位置。


http://www.ppmy.cn/news/316104.html

相关文章

实心轮胎的优缺点

实心轮胎的一些主要优点是&#xff1a; 它们从头开始设计为一个整体&#xff1a;没有移动部件或附加组件。它们与现有的 OEM 车轮配合使用。橡胶化合物可根据应用定制。它们具有出色的侧壁保护。 与泡沫填充轮胎相比&#xff0c;每小时成本更低。由于机器生产率的提高和停机时…

运动耳机哪个牌子好?蓝牙运动耳机推荐

作为一个运动狂人&#xff0c;音乐对于我来说说就是挂在耳朵上的兴奋剂。戴上耳机&#xff0c;腰不酸了腿不麻了&#xff0c;又能上两片重量了。但是对于运动耳机我的要求更高&#xff0c;长期佩戴时是否舒适、防水防汗性能如何&#xff0c;配戴的时候稳不稳固&#xff0c;音质…

2.Tomcat优化

文章目录 Tomcat优化配置文件优化系统内核优化JVM优化 Tomcat优化 Tomcat默认安装下的缺省配置并不适合生产环境&#xff0c;它可能会频繁出现假死现象需要重启&#xff0c;只有通过不断压测优化才能让它最高效率稳定的运行。优化主要包括三方面&#xff0c;分别为 操作系统优…

用于计算机视觉的 OpenCV(C++ 与 Python)与 MATLAB之间的优缺点比较

我们经常混淆我们的工具和我们的手艺。工具可以帮助你练习手艺,但它们并不能使你成为一名优秀的工匠。一个好工匠的口袋里有许多不同的工具,她会明智地使用适合工作的工具。她没有嫁给这些工具。她嫁给了她的手艺。 我经常被关于编程语言的战争逗乐。人们对哪一个更好有非常…

锤子手机调试模式

锤子手机的调试模式&#xff1a; 1、手机进入“设置”界面&#xff0c;进入后下拉菜单到最下方&#xff0c;点击“高级设置”; 2、进入“高级设置”界面后&#xff0c;点击“开发者选项”&#xff0c;在“开发者选项”界面便可以看到“USB调试”。 然而&#xff0c;如果选…

2.20 锤子剪刀布

【问题描述】 大家应该都会玩“锤子剪刀布”的游戏。现给出两人的交锋记录&#xff0c;请统计双方的胜、平、负次数&#xff0c;并且给出双方分别出什么手势的胜算最大。【输入形式】 输入第1行给出正整数N&#xff08;<105&#xff09;&#xff0c;即双方交锋的次数。随后…

PTA1018 锤子剪刀布

题目&#xff1a; 输入格式&#xff1a; 输入第 1 行给出正整数 N&#xff08;≤10^5&#xff09;&#xff0c;即双方交锋的次数。随后 N 行&#xff0c;每行给出一次交锋的信息&#xff0c;即甲、乙双方同时给出的的手势。C 代表“锤子”、J 代表“剪刀”、B 代表“布”&…

股票中阳线锤子什么意思?

阳线锤子&#xff1a;市场在做空一段时间后&#xff0c;价格不断下跌&#xff0c;卖方力量逐步消耗&#xff0c;而买方力量慢慢积聚&#xff0c;在某一交易日&#xff0c;价格大幅下跌&#xff0c;但底部此时以明显呈现极强的吸纳愿望&#xff0c;有买家大力将价格上推&#xf…