各功能寄存器的复位值如下:
堆栈指针
SP
的复位值为
07H
,累加器
ACC
、寄存器
B
的复位值为
00H
,数据指针
DP
TR
的复位值为
0000H
,而
p0
、
p1
、
p2
、
p3
四个口的复位值为
0FFH
。其他
SFR
如
PS
W
、
TCON
、
TMOD
、
TL0
、
TH0
、
TL1
、
TH1
的复位值也为
00H
。
wave
中是低
128
字节和高
128
字节(
0-7FH
),低
128
字节是片内
RAM
区,高
128
字
节(
80-FFH
)是
SFR
(特殊功能寄存器)
bit
则是位于低
128
字节的
20H .. 2FH
区域,
即
data
的
20H .. 2FH
区域
code
是在
0000H .. 0FFFFH
之间的一个代码地址。
我用
ORG 5000H
TAB: DB 22H,3BH,43H,66H,5H,6DH,88H
后,
CODE
从
5000H
开始以后变成
DB
各位
data
是在
0
到
127
之间的一个数据存储器地址,或者加
128 .. 255
范围内的一个特殊功能寄
存器(
SFR
)地址。两者访问的方式不同。实际上由于
PSW
的复位设置
PSW.3=RS0
和
PSW.4=RS1
皆为
0
,
所以通用工作寄存器区就是第
0
区,
所以
data
的
00--07H
部分是与
REG
栏中的
R0--R7
对应的。以后的则仅代表低
128
字节的内部
RAM
。
idata
是
0 to 255
范围内的一个
idata
存储器地址
idata
与
data
重合低
128
字节,有的地方只有
DATA
表示
256
字节的片内
RAM,
xdata
是
0
-
65535
范围内的一个
xdata
存储器地址。
指针类型和存储区的关系详解
一、存储类型与存储区关系
data --->
可寻址片内
ram
bdata --->
可位寻址的片内
ram
idata --->
可寻址片内
ram
,允许访问全部内部
ram
pdata --->
分页寻址片外
ram (MOVX @R0) (256 BYTE/
页
)
xdata --->
可寻址片外
ram (64k
地址范围
FFFFH)
code --->
程序存储区
(64k
地址范围
),
对应
MOVC @DPTR
二、指针类型和存储区的关系
对变量进行声明时可以指定变量的存储类型如
:
uchar data x
和
data uchar x
相等价都是在内
ram
区分配一个字节的变量。
同样对于指针变量的声明,
因涉及到指针变量本身的存储位置和指针所指向的存储区
位置不同而进行相应的存储区类型关键字的
使用如:
uchar xdata * data pstr
是指在内
ram
区分配一个指针变量
("*"
号后的
data
关键字的作用
)
,而且这个指针本
身指向
xdata
区
("*"
前
xdata
关键字的作用
)
,
可能初学
C51
时有点不好懂也不好记。没关系,我们马上就可以看到对应
“*”
前后不同
的关键字的使用在编译时出现什么情况。
......
uchar xdata tmp[10]; //
在外
ram
区开辟
10
个字节的内存空间,地址是外
ram
的
0x0
000
-
0x0009
......
第
1
种情况
:
uchar data * data pstr;
pstr="tmp";
首先要提醒大家这样的代码是有
bug
的
,
他不能通过这种方式正确的访问到
tmp
空
间。
为什么?我们把编译后看到下面的汇编
代码:
MOV 0x08,#tmp(0x00) 0x08
是指针
pstr
的存储地址
看到了吗!本来访问外
ram
需要
2 byte
来寻址
64k
空间,但因为使用
data
关键字
(
在
"*"
号前的那个
)
,所以按
KeilC
编译环境来说
就把他编译成指向内
ram
的指针变量了,
这也是初学
C51
的朋友们不理解各个存储类型
的关键字定义而造成的
bug
。特别是当工程中的
默认的存储区类为
large
时,又把
tmp[10]
声明为
uchar tmp[10]
时,这样的
bug
是很隐
秘的不容易被发现。
第
2
种情况
:
uchar xdata * data pstr;
pstr = tmp;
这种情况是没问题的,这样的使用方法是指在内
ram
分配一个指针变量
("*"
号后的
d
ata
关键字的作用
)
,而且这个指针本身指向
xdata
区
("*"
前
xdata
关键字的作用
)
。编译后的汇编代码如下。
MOV 0x08,#tmp(0x00) 0x08
和
0x09
是在内
ram
区分配的
pstr
指针变量地址空
间
MOV 0x09,#tmp(0x00)
这种情况应该是在这里所有介绍各种情况中效率最高的访问外
ram
的方法了,请大
家记住他。
第
3
种情况
:
uchar xdata * xdata pstr;
pstr="tmp";
这中情况也是对的,但效率不如第
2
种情况。编译后的汇编代码如下。
MOV DPTR, #0x000A 0x000A,0x000B
是在外
ram
区分配的
pstr
指针变量地址空
间
MOV A, #tmp(0x00)
MOV @DPTR, A
INC DPTR
MOV A, #tmp(0x00)
MOVX @DPTR, A
这种方式一般用在内
ram
资源相对紧张而且对效率要求不高的项目中。
第
4
种情况
:
uchar data * xdata pstr;
pstr="tmp";
如果详细看了第
1
种情况的读者发现这种写法和第
1
种很相似,
是的,
同第
1
种情况
一样这样也是有
bug
的,但是这次是把
pstr
分
配到了外
ram
区了。编译后的汇编代码如下。
MOV DPTR, #0x000A 0x000A
是在外
ram
区分配的
pstr
指针变量的地址空间
MOV A, #tmp(0x00)
MOVX @DPTR, A
第
5
种情况
:
uchar * data pstr;
pstr="tmp";
大家注意到
"*"
前的关键字声明没有了,是的这样会发生什么事呢?下面这么写呢!
对了用齐豫的一首老歌名来说就是
“
请跟我
来
”
,请跟我来看看编译后的汇编代码,有人问这不是在讲
C51
吗?
为什么还要给我们
看汇编代码。
C51
要想用好就要尽可能提升
C51
编译后的效率,
看看编译后的汇编会帮助大家尽快成为生产高效
C51
代码的高手的。
还
是看代码吧!
MOV 0x08, #0X01 0x08
-
0x0A
是在内
ram
区分配的
pstr
指针变量的地址空
间
MOV 0x09, #tmp(0x00)
MOV 0x0A, #tmp(0x00)
注意:
这是新介绍给大家的,
大家会疑问为什么在前面的几种情况的
pstr
指针变量都
用
2 byte
空间而到这里就用
3 byte
空间了
呢?这是
KeilC
的一个系统内部处理,在
KeilC
中一个指针变量最多占用
3 byte
空间,
对于没有声明指针指向存储空间类型的指针,
系统编译代码时都强制加载一个字节的指针类型分辩值。具体的对应关系可以参考
Kei
lC
的
help
中
C51
User’s
Guide
。
第
6
种情况
:
uchar * pstr;
pstr="tmp";
这是最直接最简单的指针变量声明,
但他的效率也最低。
还是那句话,
大家一起说好
吗!编译后的汇编代码如下。
MOV DPTR, #0x000A 0x000A
-
0x000C
是在外
ram
区分配的
pstr
指针变量地址
空间
MOV A, #0x01
MOV @DPTR, A
INC DPTR
MOV DPTR, #0x000A
MOV A, #tmp(0x00)
MOV @DPTR, A
INC DPTR
MOV A, #tmp(0x00)
MOVX @DPTR, A
这种情况很类似第
5
种和第
3
种情况的组合,既把
pstr
分配在外
ram
空间了又增加
了指针类型的分辨值。
(
本文引自
www.mcujl.com/article.asp?conID=573)
各功能寄存器的复位值如下:
堆栈指针
SP
的复位值为
07H
,累加器
ACC
、寄存器
B
的复位值为
00H
,数据指针
DP
TR
的复位值为
0000H
,而
p0
、
p1
、
p2
、
p3
四个口的复位值为
0FFH
。其他
SFR
如
PS
W
、
TCON
、
TMOD
、
TL0
、
TH0
、
TL1
、
TH1
的复位值也为
00H
。
wave
中是低
128
字节和高
128
字节(
0-7FH
),低
128
字节是片内
RAM
区,高
128
字
节(
80-FFH
)是
SFR
(特殊功能寄存器)
bit
则是位于低
128
字节的
20H .. 2FH
区域,
即
data
的
20H .. 2FH
区域
code
是在
0000H .. 0FFFFH
之间的一个代码地址。
我用
ORG 5000H
TAB: DB 22H,3BH,43H,66H,5H,6DH,88H
后,
CODE
从
5000H
开始以后变成
DB
各位
data
是在
0
到
127
之间的一个数据存储器地址,或者加
128 .. 255
范围内的一个特殊功能寄
存器(
SFR
)地址。两者访问的方式不同。实际上由于
PSW
的复位设置
PSW.3=RS0
和
PSW.4=RS1
皆为
0
,
所以通用工作寄存器区就是第
0
区,
所以
data
的
00--07H
部分是与
REG
栏中的
R0--R7
对应的。以后的则仅代表低
128
字节的内部
RAM
。
idata
是
0 to 255
范围内的一个
idata
存储器地址
idata
与
data
重合低
128
字节,有的地方只有
DATA
表示
256
字节的片内
RAM,
xdata
是
0
-
65535
范围内的一个
xdata
存储器地址。
指针类型和存储区的关系详解
一、存储类型与存储区关系
data --->
可寻址片内
ram
bdata --->
可位寻址的片内
ram
idata --->
可寻址片内
ram
,允许访问全部内部
ram
pdata --->
分页寻址片外
ram (MOVX @R0) (256 BYTE/
页
)
xdata --->
可寻址片外
ram (64k
地址范围
FFFFH)
code --->
程序存储区
(64k
地址范围
),
对应
MOVC @DPTR
二、指针类型和存储区的关系
对变量进行声明时可以指定变量的存储类型如
:
uchar data x
和
data uchar x
相等价都是在内
ram
区分配一个字节的变量。
同样对于指针变量的声明,
因涉及到指针变量本身的存储位置和指针所指向的存储区
位置不同而进行相应的存储区类型关键字的
使用如:
uchar xdata * data pstr
是指在内
ram
区分配一个指针变量
("*"
号后的
data
关键字的作用
)
,而且这个指针本
身指向
xdata
区
("*"
前
xdata
关键字的作用
)
,
可能初学
C51
时有点不好懂也不好记。没关系,我们马上就可以看到对应
“*”
前后不同
的关键字的使用在编译时出现什么情况。
......
uchar xdata tmp[10]; //
在外
ram
区开辟
10
个字节的内存空间,地址是外
ram
的
0x0
000
-
0x0009
......
第
1
种情况
:
uchar data * data pstr;
pstr="tmp";
首先要提醒大家这样的代码是有
bug
的
,
他不能通过这种方式正确的访问到
tmp
空
间。
为什么?我们把编译后看到下面的汇编
代码:
MOV 0x08,#tmp(0x00) 0x08
是指针
pstr
的存储地址
看到了吗!本来访问外
ram
需要
2 byte
来寻址
64k
空间,但因为使用
data
关键字
(
在
"*"
号前的那个
)
,所以按
KeilC
编译环境来说
就把他编译成指向内
ram
的指针变量了,
这也是初学
C51
的朋友们不理解各个存储类型
的关键字定义而造成的
bug
。特别是当工程中的
默认的存储区类为
large
时,又把
tmp[10]
声明为
uchar tmp[10]
时,这样的
bug
是很隐
秘的不容易被发现。
第
2
种情况
:
uchar xdata * data pstr;
pstr = tmp;
这种情况是没问题的,这样的使用方法是指在内
ram
分配一个指针变量
("*"
号后的
d
ata
关键字的作用
)
,而且这个指针本身指向
xdata
区
("*"
前
xdata
关键字的作用
)
。编译后的汇编代码如下。
MOV 0x08,#tmp(0x00) 0x08
和
0x09
是在内
ram
区分配的
pstr
指针变量地址空
间
MOV 0x09,#tmp(0x00)
这种情况应该是在这里所有介绍各种情况中效率最高的访问外
ram
的方法了,请大
家记住他。
第
3
种情况
:
uchar xdata * xdata pstr;
pstr="tmp";
这中情况也是对的,但效率不如第
2
种情况。编译后的汇编代码如下。
MOV DPTR, #0x000A 0x000A,0x000B
是在外
ram
区分配的
pstr
指针变量地址空
间
MOV A, #tmp(0x00)
MOV @DPTR, A
INC DPTR
MOV A, #tmp(0x00)
MOVX @DPTR, A
这种方式一般用在内
ram
资源相对紧张而且对效率要求不高的项目中。
第
4
种情况
:
uchar data * xdata pstr;
pstr="tmp";
如果详细看了第
1
种情况的读者发现这种写法和第
1
种很相似,
是的,
同第
1
种情况
一样这样也是有
bug
的,但是这次是把
pstr
分
配到了外
ram
区了。编译后的汇编代码如下。
MOV DPTR, #0x000A 0x000A
是在外
ram
区分配的
pstr
指针变量的地址空间
MOV A, #tmp(0x00)
MOVX @DPTR, A
第
5
种情况
:
uchar * data pstr;
pstr="tmp";
大家注意到
"*"
前的关键字声明没有了,是的这样会发生什么事呢?下面这么写呢!
对了用齐豫的一首老歌名来说就是
“
请跟我
来
”
,请跟我来看看编译后的汇编代码,有人问这不是在讲
C51
吗?
为什么还要给我们
看汇编代码。
C51
要想用好就要尽可能提升
C51
编译后的效率,
看看编译后的汇编会帮助大家尽快成为生产高效
C51
代码的高手的。
还
是看代码吧!
MOV 0x08, #0X01 0x08
-
0x0A
是在内
ram
区分配的
pstr
指针变量的地址空
间
MOV 0x09, #tmp(0x00)
MOV 0x0A, #tmp(0x00)
注意:
这是新介绍给大家的,
大家会疑问为什么在前面的几种情况的
pstr
指针变量都
用
2 byte
空间而到这里就用
3 byte
空间了
呢?这是
KeilC
的一个系统内部处理,在
KeilC
中一个指针变量最多占用
3 byte
空间,
对于没有声明指针指向存储空间类型的指针,
系统编译代码时都强制加载一个字节的指针类型分辩值。具体的对应关系可以参考
Kei
lC
的
help
中
C51
User’s
Guide
。
第
6
种情况
:
uchar * pstr;
pstr="tmp";
这是最直接最简单的指针变量声明,
但他的效率也最低。
还是那句话,
大家一起说好
吗!编译后的汇编代码如下。
MOV DPTR, #0x000A 0x000A
-
0x000C
是在外
ram
区分配的
pstr
指针变量地址
空间
MOV A, #0x01
MOV @DPTR, A
INC DPTR
MOV DPTR, #0x000A
MOV A, #tmp(0x00)
MOV @DPTR, A
INC DPTR
MOV A, #tmp(0x00)
MOVX @DPTR, A
这种情况很类似第
5
种和第
3
种情况的组合,既把
pstr
分配在外
ram
空间了又增加
了指针类型的分辨值。
(
本文引自
www.mcujl.com/article.asp?conID=573)