Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2373398
  • 博文数量: 145
  • 博客积分: 8668
  • 博客等级: 中将
  • 技术积分: 3922
  • 用 户 组: 普通用户
  • 注册时间: 2007-03-09 21:21
个人简介

work hard

文章分类

全部博文(145)

文章存档

2016年(1)

2015年(1)

2014年(1)

2013年(12)

2012年(3)

2011年(9)

2010年(34)

2009年(55)

2008年(20)

2007年(9)

分类: C/C++

2009-10-20 19:29:47

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

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

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 :
   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
  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
  2c:    8b 45 f8                 mov    -0x8(%ebp),%eax
  2f:    c9                       leave 
  30:    c3                       ret   

00000031 :
  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
  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
  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 :
   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
   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
  19:    5d                       pop    %ebp
  1a:    c3                       ret   
  1b:    90                       nop   
  1c:    8d 74 26 00              lea    0x0(%esi,%eiz,1),%esi

00000020 :
  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
  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
  39:    5d                       pop    %ebp
  3a:    c3                       ret   
阅读(2816) | 评论(2) | 转发(1) |
给主人留下些什么吧!~~

Godbach2009-10-25 22:40:49

是啊。不少程序效率的分析,就需要看汇编代码了。学好汇编很有用的。。。

chinaunix网友2009-10-25 22:21:18

写得好