5434|37

63

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

关于C51奇怪的问题 [复制链接]

我用keil的软件仿真运行如下代码

void main
{
  unsigned int t;

  t = 0x8000 + 0x5555;
  *(unsigned char *)t = 0xaa;
}

t = 0x8000 + 0x5555这条语句不执行。只能执行*(unsigned char *)t = 0xaa;
这是为什么?谢谢!

最新回复

对于一般的全局变量,如果中断中用到该变量(同时在主循环中也用到)一般要加volatile修饰,因为一条C转换为汇编以后可能是几条语句.当然如果转换后只有一条语句,就没有必要加  详情 回复 发表于 2007-3-28 17:38
点赞 关注

回复
举报

73

帖子

0

TA的资源

一粒金砂(初级)

沙发
 
被编译器优化掉了。
 
 

回复

87

帖子

0

TA的资源

一粒金砂(初级)

板凳
 
void main
{
  unsigned int t;

  t = 0x8000 + 0x5555;
  *(unsigned char *)t = 0xaa;
}

应该不是优化的问题吧
若被优化了,0xaa写到什么地方了
 
 
 

回复

62

帖子

0

TA的资源

一粒金砂(初级)

4
 
是语句t = 0x8000 + 0x5555;被优化了,不是t被优化掉了。
 
 
 

回复

74

帖子

0

TA的资源

一粒金砂(初级)

5
 
我大概猜到了你的目的,建议用XDATA宏。
 
 
 

回复

74

帖子

0

TA的资源

一粒金砂(初级)

6
 
我的目的是将0xaa写到0x8000 + 0x5555的地址。怎么关闭优化,XDATA宏是什么意思。谢谢!
 
 
 

回复

47

帖子

0

TA的资源

一粒金砂(初级)

7
 
       
用voliate 或者关闭优化...
 
 
 

回复

73

帖子

0

TA的资源

一粒金砂(初级)

8
 
voliate是什么,如何使用,初学51。谢谢!
 
 
 

回复

79

帖子

0

TA的资源

一粒金砂(初级)

9
 
zhuoyuesky(卓越) ( ) 信誉:100    Blog  2007-03-23 12:17:46  得分: 0  


   voliate是什么,如何使用,初学51。谢谢!
  
............................................
这个是说告诉编译器,该变量是经常使用的,一般会为这个做特殊物理,比如说放入CPU的缓存,以减小访问的代价,增加执行效率
 
 
 

回复

68

帖子

0

TA的资源

一粒金砂(中级)

10
 
t = 0x8000 + 0x5555这条语句不执行。只能执行*(unsigned char *)t = 0xaa;
这是为什么?谢谢!

因为,现在的编译器已经足够智能,只要编译的时候把T放到0x8000 + 0x5555这个地址上,这就可以省掉一个运算,提高程序的执行效率!!

从另一个侧面可以说是编译器生成代码的质量很高
 
 
 

回复

69

帖子

0

TA的资源

一粒金砂(初级)

11
 
volatile是告诉编译器不要试图优化该变量。
 
 
 

回复

76

帖子

0

TA的资源

一粒金砂(初级)

12
 
zhuoyuesky(卓越) ( ) 信誉:100    Blog  2007-03-23 12:17:46  得分: 0  


   voliate是什么,如何使用,初学51。谢谢!
  
............................................


这个是说告诉编译器,该变量是经常使用的,一般会为这个做特殊物理,比如说放入CPU的缓存,以减小访问的代价,增加执行效率

==================================================================

不要误导新网友!
 
 
 

回复

67

帖子

0

TA的资源

一粒金砂(初级)

13
 
>>t = 0x8000 + 0x5555这条语句不执行。只能执行*(unsigned char *)t = 0xaa;
这是为什么?谢谢!

编译器能将这一条语句优化掉!可能吗,智能到将一条正确而且并不是冗余的一条语句删掉.建议你看看程序其他地方有没有问题,或者关掉编译器重启试一下,这个问题最简单的办法是查看生成的对应汇编语言,看看有没有这条语句,没有那就是被优化掉了
 
 
 

回复

71

帖子

0

TA的资源

一粒金砂(初级)

14
 
zhuoyuesky(卓越) ( ) 信誉:100    Blog  2007-03-23 12:17:46  得分: 0  


   voliate是什么,如何使用,初学51。谢谢!
  
............................................


这个是说告诉编译器,该变量是经常使用的,一般会为这个做特殊物理,比如说放入CPU的缓存,以减小访问的代价,增加执行效率

==================================================================
不要误导新网友!
同意,正好说反了
 
 
 

回复

67

帖子

0

TA的资源

一粒金砂(初级)

15
 
voliate 不是常用量,是易变量,如端口。处理时不做一些默认优化。
 
 
 

回复

73

帖子

0

TA的资源

一粒金砂(初级)

16
 
对不起,重新找了相关的书籍后...

我是错的,谢谢大家指正,同时也谢谢LZ让我发现在我的知识结构中还有这样低级的缺陷,

呵呵,学习
 
 
 

回复

76

帖子

0

TA的资源

一粒金砂(初级)

17
 
但是,之后我说的下面这句被优化掉了,这个是正确的!

t = 0x8000 + 0x5555这条语句不执行。只能执行*(unsigned char *)t = 0xaa;

请看:
void main()
{
  unsigned int t;

  t = 0x8000 + 0x5555;
  *(unsigned char *)t = 0xaa;
}
这是它的C代码
C:0x0021    7AD5     MOV      R2,#0xD5
C:0x0023    7955     MOV      R1,#0x55
C:0x0025    7B00     MOV      R3,#0x00
C:0x0027    74AA     MOV      A,#0xAA

这是生成的汇编,连t这个变量都没有存在的迹像
所以,我的没错,的确是被编译器干掉了

为了向楼主和大家诚心地赔不是,我自己理解了但为了解决最终的问题,我也把分析结果大家分享一下吧...

void main()
{
  volatile unsigned int t;

  t = 0x8000 + 0x5555;
  *(unsigned char *)t = 0xaa;
}
这是加了volatile声明后,看编译器生成的代码
     3:   volatile unsigned int t;
     4:  
     5:   t = 0x8000 + 0x5555;
C:0x0003    900000   MOV      DPTR,#C_STARTUP(0x0000)
C:0x0006    74D5     MOV      A,#0xD5
C:0x0008    F0       MOVX     @DPTR,A
C:0x0009    A3       INC      DPTR
C:0x000A    7455     MOV      A,#0x55
C:0x000C    F0       MOVX     @DPTR,A
     6:   *(unsigned char *)t = 0xaa;
C:0x000D    900000   MOV      DPTR,#C_STARTUP(0x0000)
C:0x0010    E0       MOVX     A,@DPTR
C:0x0011    FE       MOV      R6,A
C:0x0012    A3       INC      DPTR
C:0x0013    E0       MOVX     A,@DPTR
C:0x0014    AA06     MOV      R2,0x06
C:0x0016    F9       MOV      R1,A
C:0x0017    7B00     MOV      R3,#0x00
C:0x0019    74AA     MOV      A,#0xAA
C:0x001B    02001E   LJMP     C?CSTPTR(C:001E)

可以清楚地看到,编译器还是把加法干掉,只留下变量t,直接事先把计算好的值送入t(地址为片外的0x0000)注:在编译的时候我把RAM设为LARGE模式,所以直接放到片外去了

这时候可以看到,虽然t没有什么意义,但是编译器还是留下了它...

这也就加深体会了我对volatile的理解

 
 
 

回复

73

帖子

0

TA的资源

一粒金砂(初级)

18
 
晕,很简单的事,对于嵌入式来说,voliate告诉编译器此变量里的值不确定,会偷偷变化,编译器在没次使用的时候要重新确认数据后再进行操作,不能使用任何中间的缓存数据,也不能做任何优化,但这与编译器优化级别设置有关。
 
 
 

回复

76

帖子

0

TA的资源

一粒金砂(初级)

19
 
嗯,错总是要改的嘛...

毛哥说:虚心使人进步
 
 
 

回复

72

帖子

0

TA的资源

一粒金砂(初级)

20
 
unsigned int t;

  t = 0x8000 + 0x5555;
  *(unsigned char *)t = 0xaa;

翻译一下:
*((unsigned char *)(unsigned int(0x8000 + 0x5555))) = 0xaa;

对Xram 赋值的意思
0x8000 + 0x5555直接就是一个数么,不被优化掉编译器岂不是太傻?
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表