原创 AVR两个c编译器和KEIL实测对比

2006-10-20 18:23 4699 7 7 分类: MCU/ 嵌入式
 曾经《AVR 高速嵌入式单片机原理及应用》的介绍:代码效率 AVR 46B 对 C51 的112B,  
再加上不同数量级上的速度, 让我激动不已.

今天,正好趁将一段 UART 通信的程序移植到 M48 的机会, 对几个编译器做了个简单对比.
keil C 的代码效率特高, 因为我太熟悉它, 对它做了最大优化; 另外也得益于 C51 的
BOOL 处理能力, 因为在我的程序中使用了 8个位变量做状态标志.C51 3B 的判断 2B 的操作和
4B 的位传送, 对 AVR 则 8B, 10B 和 18B! 再加上_testbit_() 的神勇.
    不知道 AVR 设计时是如何考虑的, 其实状态位判断在单片机里是很常用的.

ICCAVR 代码压缩 721 words before Code Compression, 650 after. 9% reduction.reduction.

WINAVR 1202 Bytes

TIMERISR
编译器      代码长度              使用寄存器
KEIL C     3EH         62字节   ACC PSW
WINAVR   A0~138  98H  152字节   R1 R0 SREG R24 R25
ICCAVR   3A~EA   B0H  176字节   R2 R16 R24 R25 SREG
      以上地址是从生成的.lss 和 .lis 文件中找到的
UARTISR
KEIL C7.5  16CH       364字节   PSW ACC R0
WINAVR  138~3FC 2C4H  708字节   R1 R0 SREG R18 R19 R20 R22 R23 R24 R25 R30 R31  
ICCAVR  0EA~476 38CH  908字节   R0 R2 R3 R4 R5 R16 R18 R24 R25 R30 R31 SREG


去掉状态标志变量的 volatile 修饰后, 代码缩小不少, 特别是 WINAVR .
ICCAVR 代码压缩 705 words before Code Compression, 646 after. 8% reduction.

WINAVR 1110  Bytes

TIMERISR
编译器      代码长度             使用寄存器
KEIL C     3EH         62字节   ACC PSW
WINAVR   A0~118  78H  120字节   R1 R0 SREG R24 R25
ICCAVR   3A~E0   A6H  166字节   R2 R16 R24 R25 SREG

UARTISR
KEIL C7.5  16CH       364字节   PSW ACC R0
WINAVR  118~3A0 288H  648字节   R1 R0 SREG R18 R19 R20 R21 R24 R25 R30 R31  
ICCAVR  0E0~456 376H  886字节   R0 R2 R3 R4 R5 R16 R18 R24 R25 R30 R31 SREG

winavr 偶然在子程序后面会莫名其妙地生成 2 个 ret

循环优化对比:
WINAVR:
            } while(--itemp);
  d0:    91 50           subi    r25, 0x01    ; 1
  d2:    e1 f7           brne    .-8          ; 0xcc

ICCAVR
006C           ;               } while(--itemp);
006C 802F              mov R24,R16
006E 8150              subi R24,1
0070 082F              mov R16,R24
0072 8823              tst R24
0074 C1F7              brne L9
  
另外, iccavr 有比较累赘的分支跳转, 比如:  
0052 2220              tst R2
0054 09F4              brne X0
0056 42C0              rjmp L6         ; 这2条应该可改为 breq L6
0058           X0: ...

对连续位处理的优化:
WINAVR:
102:    97 7f           andi    r25, 0xF7    ; 247
104:    94 60           ori    r25, 0x04    ; 4
106:    90 93 01 01     sts    0x0101, r25
    WINAVR 判断出 r25 仍是变量 _busconf 的值, 省去了 lds r25,_busconf 指令
ICCAVR:
00C2 80914600          lds R24,_busconf
00C6 877F              andi R24,247
00C8 80934600          sts _busconf,R24
00CC 8460              ori R24,4
00CE 80934600          sts _busconf,R24


如非必要,不要用 volatile 修饰变量, 它会降低优化性能

不过,ICCAVR 完善的 IDE 和 Application Builder 对开发还是有不小帮助的
PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
我要评论
0
7
关闭 站长推荐上一条 /3 下一条