51单片机的idata,xdata,pdata,data的详解

来源:互联网 发布:税收数据 编辑:程序博客网 时间:2024/04/30 02:40


各功能寄存器的复位值如下:

  

 

堆栈指针

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

种很相似,

是的,

同第

种情况

一样这样也是有

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

种很相似,

是的,

同第

种情况

一样这样也是有

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)

0 0