C语言-----函数调用过程

我们在程序运行过程中运行到一个函数,它就会自动跳转到这个函数去执行它,那么函数在内存中到底是怎么经过一系列过程调用的呢?今天来聊一聊函数调用。
指针寄存器esp,ebp
1.  首先先搞清楚函数调用中两个非常重要的指针寄存器esp,ebp。对这两个寄存器的一些理解:
esp为栈指针,用于指向栈的栈顶
ebp为帧指针,指向栈的栈底。
函数栈帧
2.  函数调用过程中需要开辟空间,用于本次函数的调用中临时变量的保存、现场保护。这块栈空间 我们称之为函数栈帧。
栈空间由高地址向低地址使用。
函数调用过程

当函数被调用的时候,执行如下操作:

1.将帧指针压入栈中:   push ebp
2.用ebp保存当前栈指针:mov ebp ,esp
3.栈指针自减,得到的内存被用来存储被调用函数的本地状态:sub esp ,4Ch
4.在函数调用时,第一个进栈的是被调用函数后的下一条指令的地址(函数调用语句的下一条可执行语句即call指令下一条指令的地址)的地址,然后是函数的各个参数,在大多数的C编译器中, 参数是由右往左入栈的,先压形参b在压形参a ,然后是函数中的局部变量。注意静态变量是不入栈的。
5.函数调用完成时,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中下一条指令,程序由该点继续运行。
题目
我们来看一道例题:


在VC6.0环境中,下⾯面代码的结果是什么?
#include <stdio.h>
void fun()
{
	int tmp=10;
	int *p = (int*)(*(&tmp+1));
	*(p-1) = 20;
}
int main()
{
	int a=0;
	fun();
	printf("a = %d\n",a);
	return 0;
}

运行结果为 20 ,是不是觉得很奇怪?我们来分析一下

分析:定义了变量a,然后调用fun()函数,进入函数内部后(&tmp+1)指向的是tmp这个变量地址的下一个地址,解引用赋给p,请看图解:
纯属个人理解,如有不准确的地方望多加指正

猜你喜欢

转载自blog.csdn.net/abc_xixi111/article/details/79949543