一、函数的调用过程
首先我们再viso studio中编写如下代码:
int add(int a, int b) { int c = a + b; return c; } int main() { int d; d = add(1,2); printf("d=%d\r\n",d); }
讯享网
反汇编后得到如下汇编代码:
讯享网int add(int a, int b) { //入栈保护现场 00B117A0 push ebp 00B117A1 mov ebp,esp 00B117A3 sub esp,0CCh 00B117A9 push ebx 00B117AA push esi 00B117AB push edi 00B117AC lea edi,[ebp-0CCh] 00B117B2 mov ecx,33h 00B117B7 mov eax,0CCCCCCCCh 00B117BC rep stos dword ptr es:[edi] 00B117BE mov ecx,offset _549F54B0_consoleapplication1@cpp (0B1C008h) 00B117C3 call @__CheckForDebuggerJustMyCode@4 (0B1120Dh) int c = a + b; 00B117C8 mov eax,dword ptr [a] 00B117CB add eax,dword ptr [b] int c = a + b; 00B117CE mov dword ptr [c],eax return c; 00B117D1 mov eax,dword ptr [c] } //add调用结束,出栈恢复现场 00B117D4 pop edi 00B117D5 pop esi 00B117D6 pop ebx 00B117D7 add esp,0CCh //回复sp指针,释放局部变量占用的内存 00B117DD cmp ebp,esp 00B117DF call __RTC_CheckEsp (0B11217h) 00B117E4 mov esp,ebp 00B117E6 pop ebp 00B117E7 ret int main() { 00CC1930 push ebp //基址指针寄存器 00CC1931 mov ebp,esp //保存当前堆栈,将栈顶指针存入ebp,当前栈顶和栈低重合 00CC1933 sub esp,0CCh //栈顶指针向下偏移0xccbyte,开辟临时变量的空间(栈空间) 00CC1939 push ebx 00CC193A push esi 00CC193B push edi 00CC193C lea edi,[ebp-0CCh] 00CC1942 mov ecx,33h 00CC1947 mov eax,0CCCCCCCCh 00CC194C rep stos dword ptr es:[edi] 00CC194E mov ecx,offset _549F54B0_consoleapplication1@cpp (0CCC008h) 00CC1953 call @__CheckForDebuggerJustMyCode@4 (0CC1221h) int d; d = add(1,2); //从这里可以看出来,函数参数的入栈方向是自有向左 00CC1958 push 2 //最右边的形参入栈 00CC195A push 1 //最左边的形参入栈 00CC195C call add (0CC1186h) 00CC1961 add esp,8 00CC1964 mov dword ptr [d],eax printf("d=%d\r\n",d); 00CC1967 mov eax,dword ptr [d] 00CC196A push eax 00CC196B push offset string "d=%d\r\n" (0CC7B30h) 00CC1970 call _printf (0CC104Bh) 00CC1975 add esp,8 } //main函数调用结束,恢复现场 00CC1978 xor eax,eax 00CC197A pop edi 00CC197B pop esi 00CC197C pop ebx 00CC197D add esp,0CCh 00CC1983 cmp ebp,esp 00CC1985 call __RTC_CheckEsp (0CC122Bh) 00CC198A mov esp,ebp 00CC198C pop ebp 00CC198D ret
寄存器知识讲解
X86/64 vc++的堆栈是从高地址向低地址生长,比如push一个32位寄存器入栈后,esp - 04H。
汇编指令讲解
sub 减计数器sub esp,04h表示将栈顶指针向下移动4个字节
总结
从上述C语言代码的反汇编来看,函数在调用的时候会对add的两个参数进行入栈操作,因此函数的形参也是需要占用栈空间的,只是形式参数占用的空间在函数调用结束后会自动释放。
函数的调用其实就是一个入栈和出栈的过程,在函数调用前调用push保护现场,在函数调用结束后调用pop恢复现场,并将sp指针恢复为函数调用前的状态,释放调用函数所占用的内存空间。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/13753.html