从汇编看函数调用传参过程

1 示例代码

#include <stdio.h>

int func(int param1 ,int param2,int param3)
{
        int var1 = param1;
        int var2 = param2;
        int var3 = param3;
 
        printf("var1=%d,var2=%d,var3=%d",var1,var2,var3);
        return var1;
}
 
int main(int argc, char* argv[])
{
        int result = func(1,2,3);
 
        return 0; 
}

2 解析

首先说明,在堆栈中变量分布是从高地址到低地址分布,EBP是指向栈底的指针,在过程调用中不变,又称为帧指针。ESP指向栈顶,程序执行时移动,ESP减小分配空间,ESP增大释放空间,ESP又称为栈指针。

2.1 调用过程

  1. 函数main执行,main的各个参数从右往左压入栈中(这样访问参数出栈的时候是从左到右的),参数param3-param1依次压栈,如图
    1
  2. 压入返回地址
    2
  3. 程序执行从main跳转到被调用函数中,EBP入栈,将ESP(当前栈顶)赋值给EBP。

当一个新的函数调用的时候,首先将旧的EBP入栈,这样是为了保存当前调用者的栈帧,然后从当前栈顶开始建立新的栈帧(将当前栈顶ESP的值作为新的栈底EBP)

push ebp
mov ebp esp

此时栈顶(ESP)和栈底(EBP)指向同一位置
3

2.2 函数执行过程

int var1 = param1;对应汇编如下:

mov 0x8(%ebp), %eax
mov %eax, -0x4(%ebp)

先将EBP+0x8地址里面的内容赋值给eax,看图中EBP+0x8刚好是param1,再把eax寄存器的内容存到ebp-0x4的位置。这个相当于开了一个新变量int,然后赋值给这个变量。其余同理。
4

2.3 函数的返回

函数返回值一般存在eax寄存器中。

mov -0x4(%ebp), %eax

之后参数依次出栈,EBP恢复原值,返回到记录的返回地址,参数param1, param2,param3依次出栈,函数调用结束。

posted @ 2024-11-19 20:20  wenli7363  阅读(2)  评论(0编辑  收藏  举报