当前位置:首页 > 单片机 > 单片机
[导读]现在的存储器已经不像七八年前那样昂贵了,但是ram相对于rom和eeprom的价格还是不可同样看待的,所以程序中节省内存在现在看来还是非常关键的。原因有以下几点:1.ram的存取速度相对于eeprom的存取速度要快很多倍,不

现在的存储器已经不像七八年前那样昂贵了,但是ram相对于rom和eeprom的价格还是不可同样看待的,所以程序中节省内存在现在看来还是非常关键的。原因有以下几点:

1.ram的存取速度相对于eeprom的存取速度要快很多倍,不在一个数量级上,主要是因为eeprom的存储要想写入就必须先擦除,而且eeprom的擦出需要成块擦除(这是由于eeprom的擦除原理是场效应管的栅极上电擦除的,为了节省成本厂家一般都是8Bytes/page 64Bytes/page),所以使用ram来处理中间的数据是能够符合速度要求的。

2.无论是xram还是eeprom都是外部存储器,在负值时都要用到16bit地址空间(8位机),这样无形中就增大了程序的code的体积并且使得速度上也受到影响,所以尽量把indata区的ram用到极限是非常有意义的。

本人总结了一些节省内存的规律,提供给大家讨论一下,看看是否可行。

1.内存分配的基本原理:

keil与其他的c语言编译器我认为从内存分配的原理上是基本相同的。总结起来,其实很简单,就是选最长的路径进行编译(话糙理不糙),例如下面的两段程序

program 1:

unsigned char a();

void b();

void main()

{

unsigned char byte1;

unsigned char byte2;

byte1 = byte2 = 3;

if( a() == 3)

{

b();

}

a();

return;

}

// a function

unsigned char a()

{

unsigned char byte_a1;

unsigned char byte_a2;

byte_a1 = byte_a2 = 3;

byte_a1 = 4;

byte_a2 = 5;

return byte_a1;

}

// b function

void b()

{

unsigned char byte_b1;

unsigned char byte_b2;

unsigned char byte_b3;

byte_b1 = byte_b2 = byte_b3 = 3;

return;

}

program 2:

void a();

void b();

void main()

{

unsigned char byte1;

unsigned char byte2;

byte1 = byte2 = 3;

a();

return;

}

// a function

void a()

{

unsigned char byte_a1;

unsigned char byte_a2;

byte_a1 = byte_a2 = 3;

if (byte_a1 == 3)

{

b();

}

byte_a1 = 4;

byte_a2 = 5;

return;

}

// b function

void b()

{

unsigned char byte_b1;

unsigned char byte_b2;

unsigned char byte_b3;

byte_b1 = byte_b2 = byte_b3 = 3;

return;

}

两段程序的作用是相同的,都是先执行函数a,然后根据byte_a1的值判断去执行b程序,但是用keil编译的结果却不相同program 1 编译的结果是data:14 code:48,而program 2 编译的结果是data:16 code:56,可见program 1 比 program 2 即节省了code又节省了内存。

看一下反汇编代码,就可以了解原因了,在a函数中调用b函数,a函数定义的byte_a1和byte_a2变量没有被释放,所以program 2 的内存分配是 8(SFR) + 1(STACK) + 2(MAIN FUNC) + 2(A FUNC) + 3(B FUNC) = 16 Bytes,而program 1 的内存分配是 8(SFR) + 1(STACK) + 3(B FUNC) = 14Bytes, 由于B函数和A函数是并行的,所以节省了a函数需要的2个字节。

这样总结看来程序不要串行,应尽量并行,充分利用有限的ram资源,这样既可以使code区变小,也可以使速度变快。

2.uncalled segment 影响内存分配:

不知道大家是否发现过当存在没有调用的函数时,内存空间很有可能会溢出,这个原因其实也非常简单例如:

program 3:

void a();

void b();

void c(unsigned char byte_input);

void main()

{

unsigned char byte1;

unsigned char byte2;

byte1 = byte2 = 3;

a();

c(3);

return;

}

// a function

void a()

{

unsigned char byte_a1;

unsigned char byte_a2;

byte_a1 = byte_a2 = 3;

if (byte_a1 == 3)

{

b();

}

byte_a1 = 4;

byte_a2 = 5;

return;

}

// b function

void b()

{

unsigned char byte_b1;

unsigned char byte_b2;

unsigned char byte_b3;

byte_b1 = byte_b2 = byte_b3 = 3;

return;

}

void c(unsigned char byte_input)

{

unsigned char byte_c;

byte_c = byte_input;

return;

}

program 3 所示如果再main.c里面调用c(3)编译后data:16,而如果不调用c(3),编译后data:17,原因是调用c(3) data = 8(SFR) + 1(STACK) + 2(MAIN FUNC) + 2(A FUNC) + 3(B FUNC) = 16Bytes,而如果不调用c(3) data = 8(SFR) + 1(STACK) + 2(MAIN FUNC) + 2(A FUNC) + 3(B FUNC) + 1(C FUNC) = 17 Bytes。

所以,建议大家如果暂时不调用的函数最好屏蔽掉,以免影响整体的内存分配。


本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

MIKROE增加了图形功能,CLANG支持ARM和RISC-V以及许多其他功能

关键字: 编译器 RISC-V架构 工业自动化

IAR Embedded Workbench for Arm已全面支持恩智浦最新的S32系列,可加速软件定义汽车的车身和舒适性应用的开发

关键字: 电机控制 电动汽车 编译器

这款新编译器专为dsPIC®数字信号控制器 (DSC)优化设计,可为实时应用定制许可选项

关键字: 编译器 数字信号控制器 自动驾驶

C语言编译器是一种用于将C语言源代码转换为可执行程序的软件工具。它的主要功能是将C语言代码翻译成机器语言,以便计算机能够理解和执行。C语言编译器通常包括预处理器、编译器、汇编器和链接器等多个组件,它们协同工作以完成编译过...

关键字: C语言 编译器 Microsoft Visual C++

IAR Embedded Workbench 9.40版本引入了与指针验证和分支目标识别(PACBTI)扩展的无缝兼容性,保护嵌入式应用程序免受各种安全攻击。

关键字: 代码 嵌入式应用程序 编译器

在过去数十年,摩尔定律一直支配着半导体的发展。随着MCU的性能越来越强,嵌入式产品也越来越智能,嵌入式软件也变得越来越复杂。编译器作为嵌入式软件开发的基础工具,将程序员编写的源代码转换为底层硬件可以执行的机器指令。一款优...

关键字: 摩尔定律 嵌入式 软件开发 编译器

Python的创始人是一位荷兰籍的程序员——吉多·范罗苏姆(Guido van Rossum),江湖外号“龟叔”。据说这个外号是由于Guido的开头与龟的拼音gui相同得来的,所以Guido也被程序员们戏称为“龟叔”。在...

关键字: Python 编译器 人工智能

单片机内部有很多的特殊功能寄存器,每个寄存器在单片机内部都分配有唯一的地址,一般我们会根据寄存器功能的不同给寄存器赋予各自的名称,当我们需要在程序中操作这些特殊功能寄存器时,必须要在程序的最前面将这些名称加以声明,声明的...

关键字: C51 数据类型 扩充定义

数据元(Data Element),也称为数据元素,是用一组属性描述其定义、标识、表示和允许值的数据单元,在一定语境下,通常用于构建一个语义正确、独立且无歧义的特定概念语义的信息单元。数据元可以理解为数据的基本单元,将若...

关键字: C51 数据类型

之后新建新的工程,添加.a文件就可以使用了,当然也可以使用keil来添加,但是keil默认的是用.lab,需要自己配置一下文件属性,改为lib文件即可。一半release sdk的时候用这种方式很关键的,毕竟自己的核心代...

关键字: keil 文件属性 lib文件
关闭
关闭