函数调用堆栈的过程

分析函数的调用过程,以一段代码为例:

#include<stdio.h>
int sum(int a,int b)
{
	int tmp=0;
	tmp=a+b;
	return tmp;
}
 
int main()
{
	int a=10;
	int b=20;
	int ret=0;
 
	ret=sum(a,b);
	printf("ret=%d\n",ret);
	return 0;
}

反汇编如下所示: 

函数调用堆栈的过程

 函数调用堆栈的过程

解析后的反汇编:

 函数调用堆栈的过程

函数调用堆栈的过程

 画出在栈中的整个过程:

函数调用堆栈的过程

总结:

总结一下吧~

1、函数的运行都是在栈上开辟内存。

2、栈是通过esp(栈顶指针)、ebp(栈底指针)两个指针来标识的。

3、对于栈上的访问都是通过栈底指针的偏移来访问的。

4、在call一个函数时,有两件事情要做:先将调用函数的下一行指令的地址压入栈中;再进行跳转。

5、在函数调用时检查函数是否申明、函数名是否相同、函数的参数列表是否匹配、函数的返回值多大。

①如果  【函数的返回值<=4个字节】,则返回值通过寄存器eax带回。

②如果  【4<函数的返回值<=8个字节】,则返回值通过两个寄存器eax和edx带回。

③如果  【函数的返回值>8个字节】,则返回值通过产生的临时量带回。

6、函数结束ret指令干了两件事:先出栈;再将出栈的值放到CPU的PC寄存器中。因为PC寄存器中永远放的是下一次执行指令的地址,所以就顺理成章的在函数调用完之后依旧接着原来的代码继续执行。

函数调用:

#include<stdio.h>
int sum(int a,int b)
{
	/*
	push ebp
	mov ebp,esp
	sub esp,44h
	push ebx
	push esi
	push edi
	lea edi,[ebp-44h]
	mov ecx,11h
	mov eax,0xccccccch
	rep stos ===>[esp,ebp]=0xcccccccc
	*/
	int tmp=0;//mov dword ptr[ebp-4],0
	tmp=a+b;
	/*
	mov eax,dword ptr[ebp+8]
	add eax,dword ptr[ebp+0ch]
	mov dword ptr[ebp-4],eax
	*/
	return tmp;//mov dword ptr[ebp-4],eax
}
/*
mov eax,dword ptr[ebp-4]
mov esp,ebp
pop ebp
ret
*/
 
int main()
{
	/*
	push ebp
	mov ebp,esp
	sub esp,44h
	push ebx
	push esi
	push edi
	lea edi,[ebp-44h]
	mov ecx,11h
	mov eax,0xccccccch
	rep stos ===>[esp,ebp]=0xcccccccc
	*/
	int a=10;//mov dword ptr[ebp-4],0Ah
	int b=20;//mov dword ptr[ebp-8],14h
	int ret=0;//mov dword ptr[ebp-0Ch],0
	ret=sum(a,b);
	/*
	mov eax,ptr[ebp-8]
	push eax
	mov ebx,ptr[ebp-4]
	push ebx
	push ecx
	call sum
	add esp,8
	mov dword ptr[ebp-0ch],eax
	*/
	printf("ret=%d\n",ret);
	return 0;

}

函数调用堆栈的过程

上一篇:2019-2020-1 20199311《Linux内核原理与分析》第二周作业


下一篇:某桌球辅助登录算法分析并转本地验证