函数调用时的开销
来源:互联网 发布:耳机知乎 编辑:程序博客网 时间:2024/05/29 04:51
问题引入
在学习C语言时,老师强调过调用函数时会有开销,但是函数调用的开销体现在哪几个方面并不十分清楚!!
举例说明
写一个两数求和的代码,此代码中不调用函数
#include <stdio.h>int main(){ int a = 10, b = 20, c = 0; c = a + b; printf("%d\n", c); return 0;}
该程序对应的反汇编如下:
#include <stdio.h>int main(){00BA13C0 push ebp 00BA13C1 mov ebp,esp 00BA13C3 sub esp,0E4h 00BA13C9 push ebx 00BA13CA push esi 00BA13CB push edi 00BA13CC lea edi,[ebp-0E4h] 00BA13D2 mov ecx,39h 00BA13D7 mov eax,0CCCCCCCCh 00BA13DC rep stos dword ptr es:[edi] int a = 10, b = 20, c = 0;00BA13DE mov dword ptr [a],0Ah 00BA13E5 mov dword ptr [b],14h 00BA13EC mov dword ptr [c],0 c = a + b;00BA13F3 mov eax,dword ptr [a] 00BA13F6 add eax,dword ptr [b] 00BA13F9 mov dword ptr [c],eax printf("%d\n", c);00BA13FC mov esi,esp 00BA13FE mov eax,dword ptr [c] 00BA1401 push eax 00BA1402 push 0BA5858h 00BA1407 call dword ptr ds:[0BA9114h] 00BA140D add esp,8 00BA1410 cmp esi,esp 00BA1412 call __RTC_CheckEsp (0BA1136h) return 0;00BA1417 xor eax,eax }00BA1419 pop edi 00BA141A pop esi 00BA141B pop ebx 00BA141C add esp,0E4h 00BA1422 cmp ebp,esp 00BA1424 call __RTC_CheckEsp (0BA1136h) 00BA1429 mov esp,ebp 00BA142B pop ebp 00BA142C ret
再写一个同样功能的程序,与之前不同的是该函数中有函数调用
#include <stdio.h>int ADD(int x, int y){ return x + y;}int main(){ int a = 10, b = 20, c = 0; c = ADD(a, b); printf("%d\n", c); return 0;}
该函数对应的反汇编如下所示:
int main(){00051A00 push ebp 00051A01 mov ebp,esp 00051A03 sub esp,0E4h 00051A09 push ebx 00051A0A push esi 00051A0B push edi int main(){00051A0C lea edi,[ebp-0E4h] 00051A12 mov ecx,39h 00051A17 mov eax,0CCCCCCCCh 00051A1C rep stos dword ptr es:[edi] int a = 10, b = 20, c = 0;00051A1E mov dword ptr [a],0Ah 00051A25 mov dword ptr [b],14h 00051A2C mov dword ptr [c],0 c = ADD(a, b);00051A33 mov eax,dword ptr [b] 00051A36 push eax 00051A37 mov ecx,dword ptr [a] 00051A3A push ecx 00051A3B call ADD (0511DBh) 00051A40 add esp,8 00051A43 mov dword ptr [c],eax printf("%d\n", c);00051A46 mov esi,esp 00051A48 mov eax,dword ptr [c] 00051A4B push eax 00051A4C push 55858h 00051A51 call dword ptr ds:[59114h] 00051A57 add esp,8 00051A5A cmp esi,esp 00051A5C call __RTC_CheckEsp (051136h) return 0;00051A61 xor eax,eax }00051A63 pop edi 00051A64 pop esi 00051A65 pop ebx 00051A66 add esp,0E4h 00051A6C cmp ebp,esp 00051A6E call __RTC_CheckEsp (051136h) 00051A73 mov esp,ebp 00051A75 pop ebp 00051A76 ret
对比以上两段代码的反汇编,可以发现有如下不同
没有调用函数
c = a + b;00BA13F3 mov eax,dword ptr [a] 00BA13F6 add eax,dword ptr [b] 00BA13F9 mov dword ptr [c],eax
调用函数
c = ADD(a, b);00051A33 mov eax,dword ptr [b] 00051A36 push eax 00051A37 mov ecx,dword ptr [a] 00051A3A push ecx 00051A3B call ADD (0511DBh) 00051A40 add esp,8 00051A43 mov dword ptr [c],eax
由以上区别可知函数调用的开销在于参数的压栈过程push、和函数的调用call。
几点说明
由于我测试的环境是VS2013,很可能是编译器对程序的运行过程进行了优化,一般来说函数的开销有以下几个方面:
1、将参数压入栈中,参数越多,开销越大
2
、将控制权转移至函数中
3
、建立新的栈帧,也就是当前函数使用的“一片”栈空间,使用ebp的值来标识新的栈帧,因此要将原栈帧首地址保存下来,方便回到原来的即调用者的栈帧
4
、恢复原栈帧,然后将控制权转移至调用者
函数虽然有一定开销,但是在该使用函数的时候还是要使用函数,只用当某个函数规模较小并且调用的次数比较频繁时,就将该函数用宏代替。
阅读全文
0 0
- 函数调用时的开销
- 函数调用的开销
- 函数调用的开销
- 函数调用的开销
- 函数调用的开销
- C语言: 函数调用的开销
- 函数调用开销
- C++primer——inline 函数避免函数调用的开销
- boost::ptime::local_time调用的开销
- 内联函数inline,无比节省开销的
- 测量系统调用开销
- 深入理解变量及方法调用的性能开销
- 执行Insert Exec时的隐藏开销
- 递归与循环的开销比较,高精度时间函数
- RTTI、虚函数和虚基类的开销分析及…
- RTTI、虚函数和虚基类的开销分析及…
- 系统调用之时间开销
- 嵌入式系统里面调用 printf 函数有多少开销,你知道吗?
- SPU/SKU/商品
- ORACLE错误代码大全(转)
- 暑期学习序章(写在前面的话)
- MRP的类型
- AngularJS第二课(指令,作用域,控制器)
- 函数调用时的开销
- RabbitMQ各种交换机类型Exchange Types介绍
- Codeforces
- MariaDB安装
- Spring入门一
- MySQL 记录不存在插入 和 存在则更新和
- Connector attribute SSLCertificateFile must be defined when using SSL with APR解决方法
- Python-Python及PyCharm的下载与安装
- 练习 2-5 编写函数 any(s1, s2),将字符串s2中的任一字符在字符串s1中第一次出现的位置作为结果返回。如果s1中不包含s2中的字符,则返回-1。