关于C51奇怪的问题

wrathydra   2007-3-23 10:31 楼主
我用keil的软件仿真运行如下代码

void main
{
  unsigned int t;

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

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

回复评论 (37)

被编译器优化掉了。
点赞  2007-3-23 10:44
void main
{
  unsigned int t;

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

应该不是优化的问题吧
若被优化了,0xaa写到什么地方了
点赞  2007-3-23 11:01
是语句t = 0x8000 + 0x5555;被优化了,不是t被优化掉了。
点赞  2007-3-23 11:35
我大概猜到了你的目的,建议用XDATA宏。
点赞  2007-3-23 11:58
我的目的是将0xaa写到0x8000 + 0x5555的地址。怎么关闭优化,XDATA宏是什么意思。谢谢!
点赞  2007-3-23 12:12
       
用voliate 或者关闭优化...
点赞  2007-3-23 12:15
voliate是什么,如何使用,初学51。谢谢!
点赞  2007-3-23 12:17
zhuoyuesky(卓越) ( ) 信誉:100    Blog  2007-03-23 12:17:46  得分: 0  


   voliate是什么,如何使用,初学51。谢谢!
  
............................................
这个是说告诉编译器,该变量是经常使用的,一般会为这个做特殊物理,比如说放入CPU的缓存,以减小访问的代价,增加执行效率
点赞  2007-3-23 12:59
t = 0x8000 + 0x5555这条语句不执行。只能执行*(unsigned char *)t = 0xaa;
这是为什么?谢谢!

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

从另一个侧面可以说是编译器生成代码的质量很高
点赞  2007-3-23 13:01
volatile是告诉编译器不要试图优化该变量。
点赞  2007-3-23 15:22
zhuoyuesky(卓越) ( ) 信誉:100    Blog  2007-03-23 12:17:46  得分: 0  


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


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

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

不要误导新网友!
点赞  2007-3-23 16:15
>>t = 0x8000 + 0x5555这条语句不执行。只能执行*(unsigned char *)t = 0xaa;
这是为什么?谢谢!

编译器能将这一条语句优化掉!可能吗,智能到将一条正确而且并不是冗余的一条语句删掉.建议你看看程序其他地方有没有问题,或者关掉编译器重启试一下,这个问题最简单的办法是查看生成的对应汇编语言,看看有没有这条语句,没有那就是被优化掉了
点赞  2007-3-23 16:17
zhuoyuesky(卓越) ( ) 信誉:100    Blog  2007-03-23 12:17:46  得分: 0  


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


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

==================================================================
不要误导新网友!
同意,正好说反了
点赞  2007-3-23 16:21
voliate 不是常用量,是易变量,如端口。处理时不做一些默认优化。
点赞  2007-3-23 16:42
对不起,重新找了相关的书籍后...

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

呵呵,学习
点赞  2007-3-23 20:45
但是,之后我说的下面这句被优化掉了,这个是正确的!

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的理解

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

毛哥说:虚心使人进步
点赞  2007-3-23 23:41
unsigned int t;

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

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

对Xram 赋值的意思
0x8000 + 0x5555直接就是一个数么,不被优化掉编译器岂不是太傻?
点赞  2007-3-24 12:14
12下一页
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复