关于变量与存储空间的解惑!(keil中)
来源:互联网 发布:html编程工具 编辑:程序博客网 时间:2024/05/02 04:16
注意 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没有用堆栈操作零时变量,所以每个函数中的变量都占用不同的地址,所以为了节省内存空间到处分配全局变量!!
- 关于变量与存储空间的解惑!(keil中)
- 在KEIL中设定数组与变量的绝对地址
- 变量的存储空间
- Keil中枚举型(enum)变量的长度大小
- Tokyo Cabinet TCHDB源码阅读——关于变长变量的高效存取(节约存储空间)
- Keil C51中变量的使用
- 关于keil多c文件工程中bit变量的声明定义问题
- 对“C++中何时对变量分配存储空间”的思考
- 关于 keil c51 头文件中变量名声明问题
- C程序中外部变量与函数关系解惑
- C程序中外部变量与函数关系解惑
- C程序中外部变量与函数关系解惑
- java解惑:变量(属性)的覆盖
- 关于keil中STARTUP.A51的研究
- NULL与“”的存储空间
- 关于在 KEIL C51 中嵌入汇编以及C51与A51间的相互调用
- keil中lib的生成与使用
- keil mdk调试过程中查看局部变量的方法
- 一位软件工程师的6年总结
- 很多抽筋的笑话!
- java收发邮件过程.
- submit 和 button的区别
- Flash组件开发研究(1):简单的新闻列表
- 关于变量与存储空间的解惑!(keil中)
- java读取 xls 文件 存入数据库
- HttpModule和Http Handler (比较与区别)
- JUnit初步
- 优秀是一种习惯---俞敏洪
- 小赌徒
- webos Psych Desktop - Web Desktop/WebOS
- 浅谈struts、spring、Hibernian
- IT创业见闻10-培养员工从技术转型到销售有多难