以文本方式查看主题
-
曙海教育集团论坛
(http://sun4.cn/bbs/index.asp)
--
单片机初中级
(http://sun4.cn/bbs/list.asp?boardid=55)
----
关于c51内存优化的帖子问题
(http://sun4.cn/bbs/dispbbs.asp?boardid=55&id=2217)
-- 作者:wangxinxin
-- 发布时间:2010-12-7 14:50:06
-- 关于c51内存优化的帖子问题
以下内容含脚本,或可能导致页面不正常的代码
天祥老师原帖如下: 对 51 <span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%B5%A5%C6%AC%BB%FA">单片机</span>内存的认识,很多人有误解,最常见的是以下两种 ① 超过变量128后必须使用compact模式编译 实际的情况是只要内存占用量不超过 256.0 就可以用 small 模式编译 ② 128以上的某些地址为特殊寄存器使用,不能给<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%B3%CC%D0%F2">程序</span>用 与 <img alt="" src="http://www.51c51.com/bbs/images/smilies/default/titter.gif" border="0" smilieid="9"/>C 机不同,51 单片机不使用线性编址,特殊寄存器与 RAM 使用重复的重复的地址。但访问时采用不同的<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%D6%B8%C1%EE">指令</span>,所以并不会占用 RAM 空间。 由于内存比较小,一般要进行内存优化,尽量提高内存的使用效率。 以 Keil C 编译器为例,small 模式下未指存储类型的变量默认为data型,即直接寻址,只能访问低 128 个字节,但这 128 个字节也不是全为我们的程序所用,寄存器 R0-R7必须映射到低RAM,要占去 8 个字节,如果使用寄存组切换,占用的更多。 所以可以使用 data 区最大为 120 字节,超出 120 个字节则必须用 idata 显式的指定为间接寻址,另外堆栈至少要占用一个字节,所以极限情况下可以定义的变量可占 247 个字节。当然,实际应用中堆栈为一个字节肯定是不够用的,但如果<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%C7%B6%CC%D7">嵌套</span>调用层数不深,有十几个字节也够有了。 为了验上面的观点,写了个例子 #define LEN 120 data UCHAR tt1[LEN]; idata UCHAR tt2[127]; void main() { UCHAR i,j; for(i = 0; i < LEN; ++i ) { j = i; tt1[j] = 0x55; } } 可以计算 R0-7(8) + tt1(120) + tt2(127) + SP(1) 总共 256 个字节 <span class="t_tag" onclick="tagshow(event)" href="tag.php?name=keil">keil</span> 编译的结果如下: Program Size: data=256.0 xdata=0 code=30 creating hex file from ".\\Debug\\Test"... ".\\Debug\\Test" - 0 Error(s), 0 Warning(s). (测试环境为 XP + Keil C 7.5) 这段代码已经达到了内存分配的极限,再定义任何全局变量或将数组加大,编译都会报错 107 这里要引出一个问题:为什么变量 i、j 不计算在内? 这是因为 i、j 是局部变量,编译器会试着将其优化到寄存器 Rx 或栈。问题也就在这了,如果局部变量过多或定义了局部数组,编译器无法将其优化,就必须使用 RAM 空间,虽然全局变量的分配经过精心计算没有超出使用范围,仍会产生内存溢出的错误! 而编译器是否能成功的优化变量是根据代码来的 上面的代码中,循环是<a style="TEXT-DECORATION: underline" href="http://www.sogou.com/sogoupedia?query=%D3%B7" target="_blank"><font color="#0000ff">臃</font></a>肿的,变量 j 完全不必要,那么将代码改成 UCHAR i; UCHAR j; for(i = 0; i < LEN; ++i ) { tt1<i> = 0x55; } 再编译看看,出错了吧! 因为编译器不知道该如何使用 j,所以没能优化,j 须占 RAM 空间,RAM 就溢出了。 (<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%D6%C7%C4%DC">智能</span>一点的编译器会自动将这个无用的变量去掉,但这个不在讨论之列了) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// <font color="#f73809" size="5">我现在仿照上面那个列子</font> <font color="#f73809" size="5">#include<reg52.h></font> <font color="#f73809" size="5">#define LEN 120 data UCHAR tt1[LEN]; idata UCHAR tt2[127]; void main() { UCHAR i,j; for(i = 0; i < LEN; ++i ) { j = i; tt1[j] = 0x55; } } </font> <font color="#f73809" size="5">在smalll模式下编译怎么出现这样的错误,在compact 和larger也出线这样的结果,怎么回事?</font> <font color="#f73809" size="5">Build target \'Target 1\' assembling STARTUP.A51... linking... *** WARNING L1: UNRESOLVED EXTERNAL SYMBOL SYMBOL: ?C_START MODULE: STARTUP.obj (?C_STARTUP) *** WARNING L2: REFERENCE MADE TO UNRESOLVED EXTERNAL SYMBOL: ?C_START MODULE: STARTUP.obj (?C_STARTUP) ADDRESS: 000DH Program Size: data=9.0 xdata=0 code=15 creating hex file from "neicun"... "neicun" - 0 Error(s), 2 Warning(s).</font> <font color="#f73809" size="5">两个警告 我认为那两个只是c编译器把他当作警告了,其实应该是错误.</font> <font color="#f73809" size="5">警告1:没有引用外部变量</font> <font color="#f73809" size="5">警告2:应该也是关于外部变量的事</font> <font color="#f73809" size="5">我定义的data 和idata都是C52自带的RAM (256Byte)没有定义外部变量,怎么说我引用了外部变量呢?</font> <font color="#f73809" size="5">谢谢大家!!!</font> </i>
说明:
上面显示的是代码内容。您可以先检查过代码没问题,或修改之后再运行.