请教 keil c 中 代码优化的问题

jankwkz88 2008-07-04 02:29:04
请问KEIL C 中代码大小的优化 有什么好方法呢?
函数中局部变量的定义顺序怎么样才是最优的?
为什么函数中的一些代码顺序不一样也会造成很大的空间变化?
...全文
1311 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
shgefu1977 2008-09-28
  • 打赏
  • 举报
回复
环境keil uVserion3, memory model选择 large:variables in xdata的时候出现如下情况

static unsigned int ADC0_result[9]

function ()
{
unsigned int kk;
int temp0;
int temp1;
unsigned char i;
...
for(i=0;i <9;i++){
Delay_ms(100); //停顿100毫秒
temp0 = AD0SL //AD0SL是寄存器
temp1 = AD0SH //AD0HL是寄存器
temp0 = temp0 >> 4;
temp1 = temp1 < < 4;
kk=temp1+temp0;
ADC0_reslut[i]=kk;
}
}

调试发现如果
i=0
temp0=AD0SL----->temp0=0x00a0
temp1=AD0SH----->temp1=0x0090
temp0=temp0>>4----->temp0=0x000a
temp1=temp1 < <4----->temp1=0x0900
kk=temp1+temp0----->kk=0x090a
但是
ADC0_result[0]=kk----->ADC0_result[0]=0x0a0a 这一句赋值不正确!!!找不到原因,类型都是正确的。

为什么0x090a会变成0x0a0a 把高位换成了低位?

更奇怪的是运行调试中,Delay_ms(100);运行好,temp1的值会莫名其妙变化,但其实没有操作!!

怎么这么奇怪,但是memory mode选择 small正常
shuiyan 2008-07-18
  • 打赏
  • 举报
回复
其实,这些问题直接看编译的汇编代码最有效,因为你能直接看出编译器做了什么动作。
另外,这种变化是跟编译器直接相关的,换一个编译器,结果就会完全不一样。
fouryu 2008-07-18
  • 打赏
  • 举报
回复
楼主要好好学习一下微机原理和单片机原理才能真正明白为什么。

首先,在一般微机里头,程序的局部变量都是存放在堆栈中,变量的顺序影响的只是变量在堆栈中的位置,堆栈中的数据在函数运行的过程中是函数独享的,改变变量的顺序对程序而言是没有多大影响的。

而51单片机的局部变量是存放在编译器指定的某个和其它函数的局部变量共用的内存空间中。这些变量存放的地方不是某个函数独享的,要和其它所有函数共用的,共用的原则就是在调用这个函数的时候,共用变量内存空间的函数不会被调用到。你的变量顺序的调整会影响到编译器对所有函数变量空间的分配,变量的顺序影响大了去啦。

另外编译器还会根据你的代码流程来删除多余代码、合并代码、将共性的处理生成函数等等操作。

你如果真想仔细看看编译器优化到底做了什么,不如写一个简单的程序,编译生成汇编代码来研究(生成的代码好像在“.m51”文件中)。
jankwkz88 2008-07-17
  • 打赏
  • 举报
回复
进行请教各位:
我改变了下变量的顺序 ,结果代码大小改变了 :
例如: BYTE i=0;
WORD j=0;
DWORD K=0;
k=i+j;

变成:
DWORD K=0;
WORD j=0;
BYTE i=0;
k=i+j;

或:
WORD j=0;
BYTE i=0;
DWORD K=0;
k=i+j;


为什么代码都一样,可是代码大小却不一样呢????呵呵多谢了

fouryu 2008-07-09
  • 打赏
  • 举报
回复
51单片机中的参数传递不是用堆栈哦。哈佛结构的CPU内部RAM非常少,没有办法用堆栈做参数传递和局部变量空间。所以传递参数和申明局部变量都需要用到数据段。Small模式下默认使用内部数据段、Large模式下默认使用外部数据段。因为用来传递参数的寄存器数量有限,如果你的函数参数的实际大小超出了寄存器传递的极限(你上面说的那个函数就属于参数太多的情况),那编译器就会自动找一块内存(外部或内部的)空间来做参数传递。

编译器为了节约内存消耗量,会根据程序流程来重用内存空间,把不冲突的函数中的变量定义到同一个地址中去。例如,如果函数A和函数B永远都不会同时使用,那A和B用到的局部变量空间就是可以重叠的。也就是说Keil在处理变量的时候是非常复杂的,具体结果和你的实际程序流程相关。具体怎么回事很难说清楚。

要真的说优化原则我也不知道,我感觉就是根据自己对51芯片的理解,以及实际的代码情况,可以手动的做些微调。所以要做优化,必须要理解51单片机的体系结构。

[Quote=引用 5 楼 shuiyan 的回复:]
keil C的C编译涉及的函数参数传递去看看,可以解决这个方面的疑问。
简单的说:参数传递涉及寄存器和堆栈,寄存器和堆栈都是8bit的,而DWORD是32bit的,放在前面,有两个寄存器不需要读进来,放在后面,就得读4次堆栈。
慢慢看吧,有这个提示也该够了。
[/Quote]
shuiyan 2008-07-06
  • 打赏
  • 举报
回复
keil C的C编译涉及的函数参数传递去看看,可以解决这个方面的疑问。
简单的说:参数传递涉及寄存器和堆栈,寄存器和堆栈都是8bit的,而DWORD是32bit的,放在前面,有两个寄存器不需要读进来,放在后面,就得读4次堆栈。
慢慢看吧,有这个提示也该够了。
jankwkz88 2008-07-05
  • 打赏
  • 举报
回复
比如说:
void fun(BYTE i,WORD j,DWORD k)
{

k=i+j;

}

变成
void fun(DWORD k, BYTE i,WORD j)
{
k=i+j;
}



void fun(DWORD k,WORD j ,BYTE i)
{
k=i+j;
}

虽然不是我实际开发的代码,但是类似,您可以试一下~~~
十分感谢您的关注,呵呵~~
shuiyan 2008-07-05
  • 打赏
  • 举报
回复
这个……太夸张了吧。你的代码很有个性,可能每个字符都给你落了号了,随便改改都有严重的后果。少见少见。
方便的话,把代码贴出来,可以一起分析。
jankwkz88 2008-07-05
  • 打赏
  • 举报
回复
我改变了下变量的顺序 ,结果代码大小改变了
例如:BYTE i;
WORD j;
变成: WORD j;
BYTE i;


还有就是函数的形参顺序变了,代码大小也改变
例如:void fun(BYTE i,WORD j,DWORD k) 变成 void fun(DWORD k, BYTE i,WORD j)

更搞笑的是 我发现我函数里有个局部变量没用 于是就删了它 结果代码大小变了 增加了100多B

还有就是函数里面的句子 前后换下位置 代码大小也变了

我主要是想优化代码的大小,结果发现很多奇怪的现象,应该是我对编译原理不懂吧~~~


希望各位指教指教阿,呵呵 无限感谢~~~
shuiyan 2008-07-04
  • 打赏
  • 举报
回复
优化要针对不同的需求和不同的代码。空讲是没法说清楚的。
局部变量的定义顺序不重要,而要和其使用联系起来才行。如果根本就没有被使用,随便你怎么定义都行。
1.1 课程内容嵌入式软件工程师的学习路线一般是:单片机、RTOS、Linux。当你掌握单片机开发后,如果要进一步提升编程水平,建议学习RTOS(Real Time Operating System,实时操作系统)。有很多优秀的RTOS,比如FreeRTOS、RT-Thread、UCOS等等。FreeRTOS使用范围最广泛,RT-Thread生态丰富,UCOS是收费的并且很少使用了。对于初学者,建议先学习FreeRTOS。只要学会了任意一款RTOS,肯定就会使用其他RTOS了。我们在2022年已经推出了“FreeRTOS快速入门”课程。为何还要重新制作“FreeRTOS入门与工程实践”?“FreeRTOS快速入门”只是讲解FreeRTOS的各类API的理论、用法、示例,这些实验是基于Keil自带的STM32F103模拟器。没有使用更多的硬件模块、不能体现工作的实际场景。在“FreeRTOS入门与工程实践”,将引入更多的硬件模块,并展示实际工程示例的用法。另外,基于RTOS的程序一般都比较复杂,涉及的源文件非常多,在工作一般都基于“面向对象”的思想来写程序。所以,本课程会涉及如下内容:讲解FreeRTOS的常用API:理论、用法选择合适的硬件模块,展示这些API的实例实现合适的小项目,展示工作的编程方法1.2 讲课方式对于每一个实验,我们会精心设计:要解决什么问题;然后讲解FreeRTOS提供的解决方法。讲解FreeRTOS的API及内部原理(不深入讲解内部源码,只是进行原理性介绍)讲解实验过程使用的模块的接口函数(只讲使用,不讲内部实现,模块的源码实现单独开课讲解)讲解原理时,配合着文档、现场画图进行讲解,跟学校老师写黑板一样最后现场从0编写程序并调试一切都是现场操作,绝对不会照着PPT念,绝对不会照着现成的代码讲解。只有现场从0操作,学员才能身临其境地学习,跟着教程:碰到问题、解决问题。1.3 硬件平台本课程基于DshanMCU-103开发套件进行开发,它由3部分组成:STM32F103C8T6的最小系统板、扩展底板、各类模块。如下图所示:  上述硬件再加一个ST-Link即可学完本课程所有内容。主板DshanMCU-103是基于STM32F103C8T6的最小系统板。之所以选择最小系统板,而不是把所有模块都放在一个整体的电路板上,目的如下:低成本尝试:嵌入式软件开发并不一定适合你,可以购买最小系统板进行体验、及时放弃按需购买:用到再买,讲究一个性价比 

27,375

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧