• 函数调用堆栈的过程(转载收藏)


    函数调用堆栈的过程(转载收藏)

    原文链接:https://blog.csdn.net/qq_41431406/article/details/96446312

    #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
    ",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
    ",ret);
        	return 0;
         
        }
    

    简单过程:
    1:压入实参 形参初始化 自右向左
    2:压下一行指令地址
    3:压调用方栈底地址
    4:跳转到被调用方函数栈帧
    5:被调用方函数活动开辟空间

  • 相关阅读:
    《构建之法》阅读笔记4
    团队冲刺第七天
    团队冲刺第六天
    团队冲刺第五天
    团队冲刺第四天
    团队冲刺第三天
    构建之法阅读笔记03
    第十四周进度条
    第二阶段冲刺站立会议10
    第二阶段冲刺站立会议09
  • 原文地址:https://www.cnblogs.com/LXY462283007/p/12833201.html
Copyright © 2020-2023  润新知