从汇编的角度看inline函数与非inline函数

来源:互联网 发布:ipad传视频软件 编辑:程序博客网 时间:2024/05/22 01:46

试验的代码如下

inline int f(int *pInt) //从*pInt加到100{   int sum = 0;   while(*pInt <= 100)   {      sum += *pInt;      (*pInt)++;   }   return sum;}int main(int argc, char *argv[]){   int x = 1, y = 2;   int a = f(&x);   int b = f(&y);   return a + b;}

在去掉了inline关键字后,汇编以上代码得到的结果如下

.file"non_inline.cpp".text.globl __Z1fPi.def__Z1fPi;.scl2;.type32;.endef__Z1fPi:       ;下面的到ret都是函数f的汇编代码LFB0:pushl%ebpLCFI0:movl%esp, %ebpLCFI1:movl8(%ebp), %ecxmovl(%ecx), %edxcmpl$100, %edxjgL4movl$0, %eaxL3:addl%edx, %eaxincl%edxcmpl$101, %edxjneL3movl$101, (%ecx)jmpL2L4:movl$0, %eaxL2:leaveLCFI2:retLFE0:.def___main;.scl2;.type32;.endef.globl _main.def_main;.scl2;.type32;.endef_main:LFB1:pushl%ebpLCFI3:movl%esp, %ebpLCFI4:andl$-16, %espLCFI5:pushl%ebxLCFI6:subl$44, %espLCFI7:call___mainmovl$1, 28(%esp);x = 1movl$2, 24(%esp);y = 2leal28(%esp), %eax;取x的地址 放到%eaxmovl%eax, (%esp);将x的地址放到栈顶call__Z1fPi;调用f函数movl%eax, %ebx;将返回值放到%ebx中leal24(%esp), %eax;取y的地址 放到%eaxmovl%eax, (%esp);将y的地址放到栈顶call__Z1fPi;调用f函数addl%ebx, %eax;%eax 已将包含f的返回值了 所以是 a + baddl$44, %esppopl%ebxLCFI8:leaveLCFI9:retLFE1:


重新加上inline关键字,进行汇编后的代码

.file"inline.cpp".def___main;.scl2;.type32;.endef.text.globl _main.def_main;.scl2;.type32;.endef_main:LFB1:pushl%ebpLCFI0:movl%esp, %ebpLCFI1:andl$-16, %espLCFI2:call___mainmovl$1, %eax;%eax保存1L2:incl%eax;%eax自增 等价于 (*pInt)++cmpl$101, %eax;和101 比较jneL2;%eax != 101 的话跳到L2movb$2, %al;%al保存2 就这样就行了应为%eax只有101 L3:incl%eax;%eax自增 等价于 (*pInt)++cmpl$101, %eax;和101 比较jneL3;%eax != 101 的话跳到L3movw$10099, %ax;将a + b的结果在编译的时候直接计算出来了leaveLCFI3:retLFE1:

可以看到没有调用函数,编译器将循环部分的代码直接放到main中,而且对代码进行了一定的优化,a+b在编译时直接计算出来了,而不是在运行期进行计算。

inline函数减少了参数的传递过程(压栈出栈),节省了call、ret指令,编译器可能还在一定程度上对代码进行优化。相对于普通的函数调用来说快了不少。

但是如果,inline函数很大的话,每一处应用inline函数的地方,将有一份相同的copy  如上面的L2和L3。这不利于空间的利用。


原创粉丝点击