关于变量与存储空间的解惑!(keil中) 收藏
注意 keil 中带有 reentrant 关键字的函数是不同于这里将要说的东西(如 void myFunc(void) reentrant { } ) //在keil 中的compact (变量被定义在pdata中) 模式不能被定义
void main (void) { int k[129]; } 在keil 中 有data 、idata 、pdata 、xdata 这几种对变量在内存中规定(后面将说到code、bdata、sfr、16sfr、bit、sbit)
//在C51的帮助中都有
unsigned char data variable; //变量的地址在RAM上(最大为128 bytes)
unsigned char idata variable; //变量的地址在RAM上(最大为256 bytes)
unsigned char pdata variable; //变量的地址在外部扩展RAM上(256 bytes 每页)
unsigned char xdata variable; //变量的地址在外部扩展RAM上(最大为64K bytes)
在编译时分配地址给变量,在生成二进制代码时把变量写成对应的地址,在程序写好后,内存就已经分配好,
13: void main (void)
14: { 15: int s[32]; 16: s[0] = 0x11; C:0x0003 750800 MOV 0x08,#0x00 //0x08为s【0】的地址,在Hex文件中已不存在s【】这个概念 C:0x0006 750911 MOV 0x09,#0x11 17: s[9] = 0x99; C:0x0009 751A00 MOV 0x1A,#0x00 C:0x000C 751B99 MOV 0x1B,#SBUF(0x99) 18: } C:0x000F 22 RET 在没有操作系统的支持时,变量的定义都是一次性的,没有谁来回收过期的内存单元。一个函数中定义了,就再也不能在另一个函数中使用这个
地址,除非是全局的。这也引出了一种使用内存的方法(全部定义成全局的,不使用局部变量,不使用参数);
C:0x0000 02002B LJMP C:002B 6: void main (void) 7: { 8: int data d[20]; 9: int idata id[39]; 10: int pdata pd[128]; 11: int xdata xd[32640]; 12: d[0] = 0x11; ;mov 直接寻址 C:0x0003 750800 MOV 0x08,#0x00 C:0x0006 750911 MOV 0x09,#0x11 13: id[38] = 0x22; ;mov 间接寻址 C:0x0009 787C MOV R0,#0x7C C:0x000B 7600 MOV @R0,#0x00 C:0x000D 08 INC R0 C:0x000E 7622 MOV @R0,#0x22 14: pd[0] = 0x33; ;movx 八位地址@R0 间接寻址 C:0x0010 7800 MOV R0,#0x00 C:0x0012 E4 CLR A C:0x0013 F2 MOVX @R0,A C:0x0014 08 INC R0 C:0x0015 7433 MOV A,#0x33 C:0x0017 F2 MOVX @R0,A 15: xd[0] = 0x44; ;movx 十六位地址@DPTR 间接寻址 C:0x0018 900100 MOV DPTR,#0x0100 C:0x001B E4 CLR A C:0x001C F0 MOVX @DPTR,A C:0x001D A3 INC DPTR C:0x001E 7444 MOV A,#0x44 C:0x0020 F0 MOVX @DPTR,A 16: xd[32639] = 0x55; ;movx 十六位地址@DPTR 间接寻址 C:0x0021 90FFFE MOV DPTR,#0xFFFE C:0x0024 E4 CLR A C:0x0025 F0 MOVX @DPTR,A C:0x0026 A3 INC DPTR C:0x0027 7455 MOV A,#0x55 C:0x0029 F0 MOVX @DPTR,A 17: } 函数的参数与内存分配!【compact模式下】 //如果下面的代码中的 int pdata pd[124]; 中124改为比他跟大的数,将通不过编译 //通过查看汇编代码可知:函数的参数也是要占内存空间的,这里通过R0~R7寄存器组来传递! 13: void main (void)
14: { 15: int data d[20]; 16: int idata id[39]; 17: int pdata pd[124]; 18: int xdata xd[32640]; 19: d[0] = 0x11; 20: id[38] = 0x22; 21: pd[0] = 0x33; 22: xd[0] = 0x44; 23: xd[32639] = 0x55; 24: 25: } C:0x002A 22 RET 3: void func1 (int s ,int k) ;编译函数时参数的地址就固定了! C:0x002B 7800 MOV R0,#0x00 ;通过R0传递参数 C:0x002D EE MOV A,R6 C:0x002E F2 MOVX @R0,A C:0x002F 08 INC R0 C:0x0030 EF MOV A,R7 C:0x0031 F2 MOVX @R0,A C:0x0032 08 INC R0 C:0x0033 EC MOV A,R4 C:0x0034 F2 MOVX @R0,A C:0x0035 08 INC R0 C:0x0036 ED MOV A,R5 C:0x0037 F2 MOVX @R0,A 4: { 5: 6: } 7: C:0x0038 22 RET 8: void func2 (int s ,int k) ;编译函数时参数的地址就固定了! C:0x0039 7804 MOV R0,#0x04 ;通过R0传递参数 C:0x003B EE MOV A,R6 C:0x003C F2 MOVX @R0,A C:0x003D 08 INC R0 C:0x003E EF MOV A,R7 C:0x003F F2 MOVX @R0,A C:0x0040 08 INC R0 C:0x0041 EC MOV A,R4 C:0x0042 F2 MOVX @R0,A C:0x0043 08 INC R0 C:0x0044 ED MOV A,R5 C:0x0045 F2 MOVX @R0,A 9: { //如果没有必要,变量还是定义成char吧! ///////////////////////////////////////////////////// //字符串 4: void main (void)
5: { 6: char * data p = "ab"; C:0x0003 7BFF MOV R3,#0xFF C:0x0005 7A00 MOV R2,#0x00 C:0x0007 793F MOV R1,#0x3F C:0x0009 8B08 MOV 0x08,R3 C:0x000B 8A09 MOV 0x09,R2 C:0x000D 890A MOV 0x0A,R1 7: char data c = 'A'; C:0x000F 750B41 MOV 0x0B,#0x41 8: char data *x = &c; C:0x0012 7F0B MOV R7,#0x0B 9: *x = 0x11; C:0x0014 A807 MOV R0,0x07 C:0x0016 7611 MOV @R0,#0x11 10: *p = 0x22; C:0x0018 7422 MOV A,#0x22 C:0x001A 120021 LCALL C?CSTPTR(C:0021) 11: P0 = *x; C:0x001D E6 MOV A,@R0 C:0x001E F580 MOV P0(0x80),A 12: } //从上面(还有实验结果)可以看出对字符串和其他变量的内存分配是不一样的!
//在VS2005中 void main (void) { char *test = "xxxx"; *test = 'A'; //异常 } void main (void )
{ char *p = "AAA"; char bmp[10] = {'1','2','3','4','5','6','7','8','9','0'}; } //初步分析,字符串被分配到了代码段中!是不能被访问的!
+ bmp 0x0012ff48 "12345678990" char [10] + p 0x00415650 "AAA" char * //他们被分配的地址相差很多 ///////////其他类型(Keil中)[可以参看C51的帮助] code ///function的默认类型 char code ar[100]; 也可以把变量放到code段
bit //申明一个位变量
static bit done_flag = 0; /* bit variable */ sfr、sfr16 特殊功能寄存器
sfr PSW = 0xD0; sfr16 T2 = 0xCC; /* Timer 2: T2L 0CCh, T2H 0CDh */ sbit 特殊功能寄存器的位
sbit name = sfr-address ^ bit-position; bdata //申明可位寻址的变量
//另外,指针所占的字节数也和data\xdata。。。有关
char data *p; //p 占1 个字节
char xdata *p; //p 占3 个字节
结束!
做一点补充:
void func(void)
{ char sz[100]; sz[0] = 0x11; sz[1] = 0x22; sz[2] = 0x33; } void func2(void)
{ char sz[100]; sz[0] = 0x11; sz[1] = 0x22; } void main(void)
{ func(); func2(); } func,和func2两个函数所占用的总内存不是200,而是100,C51处理局部变量不是通过堆栈来实现的,而是从固定地址开始分配变量0x08,0x09..... 这是我以前一直误会的地方,以前总以为C51没有用堆栈操作零时变量,所以每个函数中的变量都占用不同的地址,所以为了节省内存空间到处分配全局变量!!
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/by674868212/archive/2009/04/17/4088524.aspx
|
|