当前位置:首页 > 单片机 > 单片机
[导读]看到这篇C51的内存分配和优化的文章,个人觉得分析的十分到位,在这里转给大家C51的内存分配不同于一般的PC,内存空间有限,采用覆盖和共享技术。在Keil编译器中,经过编译后,会形成一个M51文件,在其内部可以详细的

看到这篇C51的内存分配和优化的文章,个人觉得分析的十分到位,在这里转给大家

C51的内存分配不同于一般的PC,内存空间有限,采用覆盖和共享技术。在Keil编译器中,经过编译后,会形成一个M51文件,在其内部可以详细的看到内存的分配情况。

C51内存常见的两个误区:

(1) 变量超过128字节后必须用COMPACT模式。

其实,只要不超过256字节,都可以用SMALL模式

(2) 内部RAM,128字节以上的是SFR用,不给程序用。

其实,由于C51寻址的不同,高128字节也可以用来存储变量,虽与SFR地址相同,但寻址的方式不同。

下面通过几个程序来看内存的分配。

*******************************************************************************

//程序1:

#include

void main()

{}

Program Size: data=9.0 xdata=0 code=16

TYPE BASE LENGTH RELOCATION SEGMENT NAME

-----------------------------------------------------

* * * * * * * D A T A M E M O R Y * * * * * * *

REG 0000H 0008H ABSOLUTE "REG BANK 0"

IDATA 0008H 0001H UNIT ?STACK

*******************************************************************************

从上面可以看到,即使程序内部无任何变量和函数data也会为9.0。这9个字节内存分别为R0-R8和一个堆栈指针(C51的堆栈是“grow up”,即使堆栈中没有内容,也会有一个栈底指针)。data区中由于R0-R8占有8个存储空间,因此data区最大为120字节(栈在所有的变量空间 之后),如果超过120个字节则由idata显式的指定为间接寻址。对于整个内部256字节的RAM,在极端的情况下,最大的变量为247字节。

当定义全局变量时

*******************************************************************************

//程序2:

#include

#define uint unsigned int

#define uchar unsigned char

uchar a;

uint b;

void main()

{}

Program Size: data=12.0 xdata=0 code=16

TYPE BASE LENGTH RELOCATION SEGMENT NAME

-----------------------------------------------------

* * * * * * * D A T A M E M O R Y * * * * * * *

REG 0000H 0008H ABSOLUTE "REG BANK 0"

DATA 0008H 0003H UNIT ?DT?MAIN

IDATA 000BH 0001H UNIT ?STACK

* * * * * * * C O D E M E M O R Y * * * * * * *

CODE 0000H 0003H ABSOLUTE

CODE 0003H 000CH UNIT ?C_C51STARTUP

CODE 000FH 0001H UNIT ?PR?MAIN?MAIN

*******************************************************************************

存在全局变量时,根据全局变量的类型分配相应的存储空间。

看下面的程序

*****************************************************************

//程序3:

#include

#define uint unsigned int

#define uchar unsigned char

uchar a;

uint b;

uint sum(uint c)

{

uint d;

d = c;

return d;

}

void main()

{}

Program Size: data=12.0 xdata=0 code=17

TYPE BASE LENGTH RELOCATION SEGMENT NAME

-----------------------------------------------------

* * * * * * * D A T A M E M O R Y * * * * * * *

REG 0000H 0008H ABSOLUTE "REG BANK 0"

DATA 0008H 0003H UNIT ?DT?MAIN

IDATA 000BH 0001H UNIT ?STACK

* * * * * * * C O D E M E M O R Y * * * * * * *

CODE 0000H 0003H ABSOLUTE

CODE 0003H 000CH UNIT ?C_C51STARTUP

CODE 000FH 000CH UNIT ?PR?MAIN?MAIN

CODE 001BH 0001H UNIT ?PR?_SUM?MAIN

********************************************************************

与上面的程序想比较,发现内存并没有任何的变化。

看下面的程序

***************************************************************************

//程序4:

#include

#define uint unsigned int

#define uchar unsigned char

uchar a;

uint b;

uint sum(uint c)

{

uint d;

d = c;

return d;

}

void main()

{

b = sum(5);

}

Program Size: data=12.0 xdata=0 code=28

TYPE BASE LENGTH RELOCATION SEGMENT NAME

-----------------------------------------------------

* * * * * * * D A T A M E M O R Y * * * * * * *

REG 0000H 0008H ABSOLUTE "REG BANK 0"

DATA 0008H 0003H UNIT ?DT?MAIN

IDATA 000BH 0001H UNIT ?STACK

* * * * * * * C O D E M E M O R Y * * * * * * *

CODE 0000H 0003H ABSOLUTE

CODE 0003H 000CH UNIT ?C_C51STARTUP

CODE 000FH 000CH UNIT ?PR?MAIN?MAIN

CODE 001BH 0001H UNIT ?PR?_SUM?MAIN

****************************************************************************

这与上面的内存使用相同,在这个程序中通过反汇编,查看编译后的汇编程序可以发现,参数的传递通过通用寄存器完成,没有占用新的内存。编译器将其优 化的通用寄存器(寄存器一般传递3个参数,超过3个参数时,多余的参数通过分配空间地址的方式来访问。但是分配的内存空间包含了寄存器传递的3个参数在内 的所有参数的空间。详见《Parameter And Local Variable 》和《Parameter and Register》)和栈中(程序7),但是如果参数或局部变量过多,则情况就完全不同(程序6)。

再看下面的程序

*******************************************************************

//程序5

#include

#define uint unsigned int

#define uchar unsigned char

uchar a;

uint b;

uint sum(uint c)

{

uint d;

}

void main()

{

}

Program Size: data=16.0 xdata=0 code=21

TYPE BASE LENGTH RELOCATION SEGMENT NAME

-----------------------------------------------------

* * * * * * * D A T A M E M O R Y * * * * * * *

REG 0000H 0008H ABSOL

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

嵌入式开发作为一种专业且技术密集型的领域,涵盖了从硬件底层驱动、中间件到应用层软件开发等多个层面的工作,其所需的工具种类繁多,各有针对性,旨在提升开发效率、保证代码质量以及简化调试过程。

关键字: 嵌入式开发 keil

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

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

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

关键字: C51 数据类型

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

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

↓推荐关注↓前言堆内存(HeapMemory)是一个很有意思的领域。你可能和我一样,也困惑于下述问题很久了:如何从内核申请堆内存?谁管理它?内核、库函数,还是应用本身?内存管理效率怎么这么高?!堆内存的管理效率可以进一步...

关键字: 分配器 内存分配 BSP THREAD

关注、星标公众号,直达精彩内容文章来源:技术让梦想更伟大整理:李肖遥前言由于malloc()的源码十分的繁琐,并且会调用OS所提供的API,所以我不在对malloc()的源码进行分析了,而只是会分析malloc()的动作...

关键字: 内存分配 GROUP TE COOKIE

▼点击下方名片,关注公众号▼欢迎关注【玩转单片机与嵌入式】公众号,回复关键字获取更多免费资料。回复【加群】,限时免费进入知识共享群;回复【3D封装库】,常用元器件的3D封装库;回复【电容】,获取电容、元器件选型相关的内容...

关键字: C51 MDK RealView

Understandingglibcmalloc日志:[2019-10-10]经评论@kwdecsdn提醒,新增对「UnsortedBin中的chunks何时移至small/largechunk中」的补充解释。[2019...

关键字: 分配器 内存分配

Understandingglibcmalloc日志:[2019-10-10]经评论@kwdecsdn提醒,新增对「UnsortedBin中的chunks何时移至small/largechunk中」的补充解释。[2019...

关键字: 分配器 内存分配

在Keil C51软件中51单片机的中断服务和外设驱动程序的开发

关键字: keil5 编译 C51
关闭
关闭