keil c51优化等级介绍

keil c51 有9个优化等级,请问每一级的优化代表什么呢?
我的程序使用第四级优化和第八,第九级的时候出问题了;

一般用优化等级8,其它的别用,容易出事。
编译完之后多留意data,xdata,看有没超出芯片的最大值,
特别是data,不能超过128,甚至太接近128有时也会出问题。
如果data 需要使用到256,则另外的128用idata定义
温馨提示:答案为网友推荐,仅供参考
第1个回答  2010-12-09
用C语言的话把KEIL的优化等级调到9级,默认是8级,最好是编写和调试同步进行,这样确保程序的可调控性吧,对后续代码维护有很大的帮助。

关于swith和指针语句,可以去看KEIL的英文版帮助,或者51bbs发布的KEIL中文帮助手册,比较全面的,理解了帮助文件后,再从KEIL中对C程序看相应的汇编代码,加深理解。

比较通用的办法,就是用不同的C语句实现相同的功能,再通过汇编窗口观察生成的汇编代码做对比,找到最少量的汇编代码生成方式,以后再用C写程序的时候就按你找到的这个方式写。
第2个回答  2012-06-04
Keil的代码优化产生的问题\
阅 读了《单片机与嵌入式系统应用》2005年第10期杂志《经验交流》栏目的一篇文章《Keil C5l对同一端口的连续读取方法》(原文)后,笔者认为该文并未就此问题进行深入准确的分析。文章中提到的两种解决方法并不直接和简单。笔者认为这并非是 Keil C51中不能处理对一个端口进行连续读写的问题,而是对Keil C51的使用不够熟悉和设计不够细致的问题,因此特撰写本文。
本文中对原文提到的问题,提出了三种不同于原文的解决方法。每种方法都比原文中提到的方法更直接和简单,设计也更规范。(无意批评,请原文作者见谅)
1 问题回顾和分析
原文中提到:在实际工作中遇到对同一端口反复连续读取,Keil C5l编译并未达到预期的结果。原文作者对C编译出来的汇编程序进行分析发现,对同一端口的第二次读取语句并未被编译。但可惜原文作者并未分析没有被编译 的原因,而是匆忙地采用一些不太规范的方法试验出了两种解决办法。
对此问题,翻阅Keil C51的手册很容易发现:KellC51的编译器有一个优化设置,不同的优化设置,会产生不同的编译结果。一般情况缺省编译优化设置被设定为8级优化,实际最高可设定为9级优化:
①Dead code elimination。
②Data overlaymg。
③Peephole optimization。
④Register variables。
⑤Common subexpression elimination。
⑥Loop rotation。
⑦Extended Index Access 0ptimizing。
⑧Reuse Common。Entry Code。
⑨Common Block Subroutines。
而以上的问题,正是由于KeiI C5l编译优化产生的。因为在原文程序中将外设地址直接按如下定义:
unsigned char xdata MAXl97_at_Ox8000;
采用_at_将变量MAXl97定义到外部扩展RAM指定地址Ox8OOO。因此,Keil C51优化编译理所当然认为重复读第二次是没有用的,直接用第一次读取的结果就可以了,因此编译器跳过了第二条读取语句。至此,问题就一目了然了。
2 解决方法
由以上分析很容易就能提出很好的解决办法。
2.1 最简单最直接的办法
程序一点都不用修改,将Keil C5l的编译优化选择设置为0(不优化)就可以了。
选择project窗口的Target,然后打开“Options forTarget”设置对话框,选择“C5l”选项卡,将“Code Optimiztaion”中的“Level”选择为“0:Costant folding”。再次编译后,大家会发现编译结果为:
CLR MAXHBEN
MOV DPTR,#M.AXl97
MOVX A,@DPTR
MOV R7.A
MOV down8.R7
SETB MAXHBEN
MOV DPTR,#MAXl97
MOVX A,@DPTR
MOV R7.A
MOV uD4.R7
两次读取操作都被编译出来了。
2.2 最好的方法
告诉Keil C51,这个地址不是一般的扩展RAM,而是连接的设备,具有“挥发”特性,每次读取都是有意义的。
可以修改变量定义,增加“volatile”关键字说明其特征:
unsigned char volatile xdata MAXl97_at_Ox8000;
也可以在程序中包含系统头文件:“#incIude”,然后在程序中修改变量,定义为直接地址:
#defme MAXl97 XBYTE[Ox8000]
这样,。Keil C51的设置仍然可以保留高级优化,且编译结果中,同样两次读取并不会被优化跳过。
2.3 硬件解决方法
原文中将MAXl97的数据直接连接到数据总线,而对地址总线并未使用,采用一根端口线选择操作高低字节。很简单的修改方法就是使用一根地址线选择操作高 低字节即可。比如:将P2.0(A8)连接到原来P1.O连接的HBEN脚(MAXl97的5脚),在程序中分别定义高低字节的操作地址:
unsigned char volatile xdata MAXl97_L_aI_Ox8000;
unsigned char volatile xdata MAXl97 H at 0.x8100;
将原来的程序:
MAXHBEN=O; //读取低8位
down8=MAXl97:
MAXHBEN=1; //读取高4位
up4=MAXl97:
改为以下两句即可:
down8=MAXl97_L; //读取低8位
up4=MAXl97_H; //读取高4位
3 小结
Keil C51经过长期考验和改进以及大量开发人员的实际使用,已经克服了绝大多数的问题,并且其编译效率也非常高。对于一般的使用,很难再发现什么问题。笔者曾 经粗略研究过一下Keil C51优化编译的结果,非常佩服Keil C51设计者的智慧,一些C程序编译产生的汇编代码,甚至比一般程序员直接用汇编编写的代码还要优秀和简练。通过研读KeilC51编译产生的汇编代码, 对提高汇编语言编写程序的水平都是很有帮助的。
由本文中的问题可以看出:在设计中遇到问题时,一定不要被表面现象蒙蔽,不要急于解决。应该认真分析,找出问题的原因,这样才能从根本上彻底解决问题。上不会出现不必要的干扰,防止了数据不一致的发生。

附表:Keil C51中的优化级别及优化作用
级别 说明
0 常数合并:编译器预先计算结果,尽可能用常数代替表达式。包括运行地址计算。
优化简单访问:编译器优化访问8051系统的内部数据和位地址。
跳转优化:编译器总是扩展跳转到最终目标,多级跳转指令被删除。
1 死代码删除:没用的代码段被删除。
拒绝跳转:严密的检查条件跳转,以确定是否可以倒置测试逻辑来改进或删除。
2 数据覆盖:适合静态覆盖的数据和位段被确定,并内部标识。BL51连接/定位器可以通 过全局数据流分析,选择可被覆盖的段。
3 窥孔优化:清除多余的MOV指令。这包括不必要的从存储区加载和常数加载操作。当存 储空间或执行时间可节省时,用简单操作代替复杂操作。
4 寄存器变量:如有可能,自动变量和函数参数分配到寄存器上。为这些变量保留的存 储区就省略了。
优化扩展访问:IDATA、XDATA、PDATA和CODE的变量直接包含在操作中。在多数时间没 必要使用中间寄存器。
局部公共子表达式删除:如果用一个表达式重复进行相同的计算,则保存第一次计算 结果,后面有可能就用这结果。多余的计算就被删除。
Case/Switch优化:包含SWITCH和CASE的代码优化为跳转表或跳转队列。
5 全局公共子表达式删除:一个函数内相同的子表达式有可能就只计算一次。中间结果 保存在寄存器中,在一个新的计算中使用。
简单循环优化:用一个常数填充存储区的循环程序被修改和优化。
6 循环优化:如果结果程序代码更快和有效则程序对循环进行优化。
7 扩展索引访问优化:适当时对寄存器变量用DPTR。对指针和数组访问进行执行速度和 代码大小优化。
8 公共尾部合并:当一个函数有多个调用,一些设置代码可以复用,因此减少程序大小 。
9 公共块子程序:检测循环指令序列,并转换成子程序。Cx51甚至重排代码以得到更大 的循环序列。