|
转载时请注明出处和作者联系方式
文章出处: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++的循环条件: 3c: 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) 1a: eb 0a jmp 26 <loop_dec+0x26> 1c: 8b 45 fc mov -0x4(%ebp),%eax 1f: 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) 2a: 7f f0 jg 1c <loop_dec+0x1c> 2c: 8b 45 f8 mov -0x8(%ebp),%eax 2f: 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) 3e: c7 45 f8 00 00 00 00 movl $0x0,-0x8(%ebp) 45: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%ebp) 4c: eb 0a jmp 58 <loop_inc+0x27> 4e: 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 5b: 3b 45 08 cmp 0x8(%ebp),%eax 5e: 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 1a: c3 ret 1b: 90 nop 1c: 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 2a: 85 c9 test %ecx,%ecx 2c: 7e 0b jle 39 <loop_inc+0x19> 2e: 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 3a: c3 ret
原文地址
http://blog.csdn.net/absurd/archive/2009/02/27/3941263.aspx
|