您的位置 首页 模拟

keil c51编译器对内存分配一些运用心得

现在的存储器已经不像七八年前那样昂贵了,但是ram相对于rom和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。
所以,主张我们假如暂时不调用的函数最好屏蔽掉,避免影响全体的内存分配。

这次先写到这儿吧,期望我们多和我评论评论,下一次我想和我们评论一下有关keil中data_group的问题。

//————————-

关于 “uncalled segment 影响内存分配” 这个问题,宣布一点观点(由于彼人也非JSJ结业).
程序源文件(c, a51文件),先通过编译得到obj文件,所谓的方针文件.各个obj文件便是一个个的模块,每个模块根本上都含有代码段和数据段,也便是说,代码在rom里边要占用多少CODE空间,数据在ram里边要占用多少ram空间等等信息.我认为lib文件也和obj文件相似,仅仅文件结构有些不一样.
obj(lib)文件然后通过l51.exe(bl51.exe),便是说把可履行代码模块依据衔接定位参数地址上衔接在一起();数据段也衔接在一起,在ram空间中分配.对ram空间的分配中就有一个衔接进程”掩盖剖析”.调用一个c函数,就会为这个函数所运用的ram空间进行分配(一些局部变量),这个函数回来时再收回分配给他的ram空间,依据函数相互之间的调用前后联系,编译器就可以时实的知道ram空间的运用情况(其中就存在一个函数重入的问题),作为衔接时ram空间分配的参数. 假如源文件中的函数(模块)从来没有被任何函数显现的调用(所谓非显现调用便是这段代码,衔接器现在还不知道这段代码什么时候会被调用或是否会被调用),衔接时就会为它分配永久有用的ram空间(就象全局变量),不会被收回.

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/zhishi/moni/255750.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部