i++ 与 i-- 循环的执行效率(转)

转载时请注明出处和作者联系方式
文章出处:http://www.limodev.cn/blog
作者联系方式:李先静 <xianjimli at hotmail dot com>

昨天同事问了我一个问题,有两个循环语句:

 
  
for (i = n; i > 0 ; i)
{

}

for (i = 0 ; i < n; i ++ )
{

}

为什么前者比后者快?

我当时的解释是:

i操作本身会影响CPSR(当前程序状态寄存器),CPSR常见的标志有N(结果为负), Z(结果为0),C(有进位),O(有溢出)。i > 0,可以直接通过Z标志判断出来。

i++操作也会影响CPSR(当前程序状态寄存器),但只影响O(有溢出)标志,这对于i < n的判断没有任何帮助。所以还需要一条额外的比较指令,也就是说每个循环要多执行一条指令。

(这是五年前tjww告诉我的,当时他在AVR上写一个LCD驱动程序,使用后者LCD会闪烁,使用前者则没有问题。)

为了确认我的理解是正确的,做了个实验:

 
  
int loop_dec( int n)
{
int i = 0 ;
int v = 0 ;

for (i = n; i > 0 ; i -- )
v
+= i;

return v;
}

int loop_inc( int n)
{
int i = 0 ;
int v = 0 ;

for (i = 0 ; i < n; i ++ )
v
+= i;

return v;
}

用arm-linux-gcc编译,然后反汇编:

i--的循环条件:
4c: e51b3014 ldr r3, [fp, #-20]
50: e3530000 cmp r3, #0 ; 0x0
54: cafffff5 bgt 30 

i++的循环条件:
b8: e51b3018 ldr r3, [fp, #-24]
bc: e1520003 cmp r2, r3
c0: bafffff4 blt 98 

结果和我想象的并不一样,这是怎么回事呢?我想可能因为没有加优化选项,于是加上-O选项,结果变为:

i--的循环条件:
 
  
14 : e2500001 subs r0, r0, # 1 ; 0x1
18 : 1afffffc bne 10

i++的循环条件:
 
  
3 c: e2833001 add r3, r3, # 1 ; 0x1
40 : e1500003 cmp r0, r3
44 : 1afffffb bne 38

这下没错了,果然少一个cmp指令。

=================================================

wangyao@wangyao-laptop:~/Test$ gcc -c t_loop.c 
wangyao@wangyao-laptop:~/Test$ objdump -d t_loop.o 

t_loop.o:     file format elf32-i386

 
  
Disassembly of section . text:

00000000 <loop_dec>:
0 : 55    push %ebp
1 : 89 e5    mov %esp,%ebp
3 : 83 ec 10    sub $0x10,%esp
6 : c7 45 fc 00 00 00 00 movl $0x0,-0x4(%ebp)
d: c7 45 f8 00 00 00 00 movl $0x0,-0x8(%ebp)
14 : 8b 45 08 mov 0x8(%ebp),%eax
17 : 89 45 fc    mov %eax,-0x4(%ebp)
1
a: eb 0a    jmp 26 <loop_dec+0x26>
1
c: 8b 45 fc    mov -0x4(%ebp),%eax
1
f: 01 45 f8    add %eax,-0x8(%ebp)
22 : 83 6d fc 01    subl $0x1,-0x4(%ebp)
26 : 83 7d fc 00    cmpl $0x0,-0x4(%ebp)
2
a: 7f f0    jg 1c <loop_dec+0x1c>
2
c: 8b 45 f8    mov -0x8(%ebp),%eax
2
f: c9    leave
30 : c3    ret

00000031 <loop_inc>:
31 : 55     push %ebp
32 : 89 e5     mov %esp,%ebp
34 : 83 ec 10    sub $0x10,%esp
37 : c7 45 fc 00 00 00 00 movl $0x0,-0x4(%ebp)
3
e: c7 45 f8 00 00 00 00 movl $0x0,-0x8(%ebp)
45 : c7 45 fc 00 00 00 00 movl $0x0,-0x4(%ebp)
4
c: eb 0a    jmp 58 <loop_inc+0x27>
4
e: 8b 45 fc    mov -0x4(%ebp),%eax
51 : 01 45 f8    add %eax,-0x8(%ebp)
54 : 83 45 fc 01    addl $0x1,-0x4(%ebp)
58 : 8b 45 fc    mov -0x4(%ebp),%eax
5
b: 3b 45 08    cmp 0x8(%ebp),%eax
5
e: 7c ee     jl 4e <loop_inc+0x1d>
60 : 8b 45 f8    mov -0x8(%ebp),%eax
63 : c9    leave
64 : c3     ret

--------------------------------------------------------------

wangyao@wangyao-laptop:~/Test$ gcc -c t_loop.c  -O2
wangyao@wangyao-laptop:~/Test$ objdump -d t_loop.o 

t_loop.o:     file format elf32-i386

 
  
Disassembly of section . text:

00000000 <loop_dec>:
0 : 55    push %ebp
1 : 31 c0   xor %eax,%eax
3 : 89 e5 mov %esp,%ebp
5 : 8b 55 08 mov 0x8(%ebp),%edx
8 : 85 d2 test %edx,%edx
a: 7e 0d jle 19 <loop_dec+0x19>
c: 8d 74 26 00 lea 0x0(%esi,%eiz, 1 ),%esi
10 : 01 d0 add %edx,%eax
12 : 83 ea 01 sub $0x1,%edx
15 : 85 d2 test %edx,%edx
17 : 7f f7 jg 10 <loop_dec+0x10>
19 : 5d pop %ebp
1
a: c3 ret
1
b: 90 nop
1
c: 8d 74 26 00 lea 0x0(%esi,%eiz, 1 ),%esi

00000020 <loop_inc>:
20 : 55 push %ebp
21 : 31 d2 xor %edx,%edx
23 : 89 e5 mov %esp,%ebp
25 : 31 c0 xor %eax,%eax
27 : 8b 4d 08 mov 0x8(%ebp),%ecx
2
a: 85 c9 test %ecx,%ecx
2
c: 7e 0b jle 39 <loop_inc+0x19>
2
e: 66 90 xchg %ax,%ax
30 : 01 d0 add %edx,%eax
32 : 83 c2 01 add $0x1,%edx
35 : 39 d1 cmp %edx,%ecx
37 : 7f f7 jg 30 <loop_inc+0x10>
39 : 5d pop %ebp
3
a: c3 ret

转载于:https://www.cnblogs.com/little-ant/archive/2011/06/03/2071195.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值