不知道是我哪里出bug了---volatile变量老是被优化

[复制链接]
2571|16
手机看帖
扫描二维码
随时随地手机跟帖
David_ming|  楼主 | 2010-4-30 21:04 | 显示全部楼层 |阅读模式
先上程序如下:
#include "NUC.h"
volatile ulong *Pt;

void InstallData(volatile ulong *Point)
{
    Pt = Point;
}

int main(void)
{
    volatile ulong i = 0;
    volatile ulong j;

    InstallData(&i);
    while(1)
    {
         j = i;
         j -= 10;
         *(volatile ulong *)0x50004000 = j;
         j -= 10;
         *(volatile ulong *)0x50004000 = j;
     }   
}
void SysTick_Handler(void)
{
     *Pt++;
}


上述程序先不管功能,那个中断也没开(编译器也不知道我开没开),注意那两个volatile变量,没想到编译器竟然给优化掉了,不知是什么问题,哪位大侠指点一下,谢谢。反汇编程序如下:

0x0000017C 610A      STR      r2,[r1,#0x10]
0x0000017E 4A07      LDR      r2,[pc,#28]  ; @0x0000019C
0x00000180 4669      MOV      r1,sp
0x00000182 6011      STR      r1,[r2,#0x00]
0x00000184 4A08      LDR      r2,[pc,#32]  ; @0x000001A8
0x00000186 380A      SUBS     r0,r0,#0x0A
0x00000188 1801      ADDS     r1,r0,r0

0x0000018A 6010      STR      r0,[r2,#0x00]
0x0000018C 6011      STR      r1,[r2,#0x00]
0x0000018E E7FC      B        0x0000018A          就一直这样跑loop了,也不执行任何运算

声明:我用的是D版的MDK :L




                 SysTick_Handler:

相关帖子

David_ming|  楼主 | 2010-5-3 10:35 | 显示全部楼层
看来我还是把标题改成MDK之bug回头率可能高一点

使用特权

评论回复
ZALIN| | 2010-5-3 15:55 | 显示全部楼层
*Pt++与你的本意不同吧

使用特权

评论回复
David_ming|  楼主 | 2010-5-3 17:44 | 显示全部楼层
本帖最后由 David_ming 于 2010-5-3 17:45 编辑

这个是瞎写的,没注意那么多,的确这句话白写了,没啥实际意义,应该加个括号(*Pt)++或者++*Pt;  关键是我的主题是volatile变量赋值被优化掉了

使用特权

评论回复
David_ming|  楼主 | 2010-5-3 18:03 | 显示全部楼层
上面那个不够明显,再发一个
volatile ulong *Pt;

int main(void)
{
     volatile ulong i;
     Pt = &i;
     while(1)
    {
         *(volatile ulong *)0x50004000 = i;
     }   
}
void SysTick_Handler(void)
{
      ++*Pt;
}



                 main:
0x00000168 B508      PUSH     {r3,lr}
0x0000016A 4906      LDR      r1,[pc,#24]  ; @0x00000184
0x0000016C 4668      MOV      r0,sp
0x0000016E 6008      STR      r0,[r1,#0x00]
0x00000170 4905      LDR      r1,[pc,#20]  ; @0x00000188
0x00000172 9800      LDR      r0,[sp,#0x00]
0x00000174 6008      STR      r0,[r1,#0x00]  //从下面的程序可以看出R0的值是定值
0x00000176 E7FD      B        0x00000174
                 SysTick_Handler:
0x00000178 4802      LDR      r0,[pc,#8]  ; @0x00000184
0x0000017A 6800      LDR      r0,[r0,#0x00]
0x0000017C 6801      LDR      r1,[r0,#0x00]
0x0000017E 1C49      ADDS     r1,r1,#1
0x00000180 6001      STR      r1,[r0,#0x00]  //更新[R0]值,R0值不变!!
0x00000182 4770      BX       lr



我真的无奈了

使用特权

评论回复
voidx| | 2010-5-4 12:16 | 显示全部楼层
本帖最后由 voidx 于 2010-5-4 12:23 编辑

注意:
volatile uint32 *pt;
uint32 *volatile pt;
volatile uint32 *volatile pt;
是不一样的。

const也类似。
const uint32 *pt;
uint32 *const pt;
const uint32 * const pt;
也是不一样的。


volatile uint32 *pt:
pt指向的存储空间是volatile,而pt本身并不是volatile.
*pt=x;  //*pt的类型含有volatile属性,不会被优化。
但是
pt=&x; //pt本身只是普通变量,不含volatile属性,可能会被优化掉。
volatile uint32 *pt:
pt指向的存储空间是volatile,而pt本身并不是volatile.
*pt=x;  //*pt的类型含有volatile属性,不会被优化。
但是
pt=&x; //pt本身只是普通变量,不含volatile属性,可能会被优化掉。

使用特权

评论回复
David_ming|  楼主 | 2010-5-4 13:45 | 显示全部楼层
6# voidx

首先感谢这位兄台支持,不过也许是我表达不清楚,我的疑问是
while(1)
{
  *(volatile ulong *)0x50004000 = i; //这句话被优化
}

上面这个循环被优化,既然 i 已经是volatile型变量,那么编译器就应该编译成取 i 的地址才对呀,可是编译器还是把寄存器的值付了进去!

还有你说的volatile uchar *volatile Pt这个问题,当然肯定是不一样的,前面的volatile修饰的是指针指向的内容,后边修饰的是Pt的值

使用特权

评论回复
David_ming|  楼主 | 2010-5-4 17:51 | 显示全部楼层
今天向MDK反映了此事,Intl(MDK的FAE)说要向RD反映一下,感谢楼上各位支持

使用特权

评论回复
linqing171| | 2010-5-4 23:16 | 显示全部楼层
优化等级低的时候代码还很多的,等级一高了,似乎少了不少。


优化等级3的时候的代码如下:


    8:      Pt = &i;
     9:      while(1)
    10:     {
0x000801E4  E59F1044  LDR       R1,[PC,#0x0044]
     6: {
     7:      volatile ulong i;
     8:      Pt = &i;
     9:      while(1)
    10:     {
0x000801E8  E24DD004  SUB       R13,R13,#0x00000004
0x000801EC  E581D000  STR       R13,[R1]
    11:          *(volatile ulong *)0x50004000 = i;
    12:      }   
    13: }
    14: void SysTick_Handler(void)
    15: {
0x000801F0  E59F103C  LDR       R1,[PC,#0x003C]
     7:      volatile ulong i;
     8:      Pt = &i;
0x000801F4  E59D0000  LDR       R0,[R13]
0x000801F8  E5810000  STR       R0,[R1]
     9:      while(1)
    10:     {
    11:          *(volatile ulong *)0x50004000 = i;
    12:      }   
    13: }
    14: void SysTick_Handler(void)
    15: {
0x000801FC  EAFFFFFD  B         0x000801F8
    16:       ++*Pt;
0x00080200  E59F0028  LDR       R0,[PC,#0x0028]
0x00080204  E5900000  LDR       R0,[R0]
0x00080208  E5901000  LDR       R1,[R0]
0x0008020C  E2811001  ADD       R1,R1,#0x00000001
0x00080210  E5801000  STR       R1,[R0]
    17: }
    18:  
    19:  
0x00080214  E12FFF1E  BX        R14
    20: void  Undef_Handler(){}
0x00080218  E12FFF1E  BX        R14
    21: void   SWI_Handler(){}

使用特权

评论回复
linqing171| | 2010-5-4 23:22 | 显示全部楼层
本帖最后由 linqing171 于 2010-5-4 23:24 编辑

while 1 一直在循环 STR       R0,[R1] 这一句。
而中断函数
LDR       R0,[PC,#0x0028] ;//pc+0028+4里面保存的是 00010000H,也就是pt的地址。
LDR       R0,[R0] ;//把pt读出来
LDR       R1,[R0];//把pt的指向的值读出来
ADD       R1,R1,#0x00000001 ;// 值++
STR       R1,[R0]  ;//保存到pt指向的地方。

中断函数使用了中断下的R0和R1.

中断函数中的R0和R1 不是用户模式的R0和R1。

被楼主忽悠了。编译器没有错。我这里测试也是这样,结果都是对的。

使用特权

评论回复
David_ming|  楼主 | 2010-5-5 15:46 | 显示全部楼层
10# linqing171

不明白你的意思,好像跟我讲的不是一回事~~ :L ,都没谈到一个主题上

使用特权

评论回复
David_ming|  楼主 | 2010-5-5 15:48 | 显示全部楼层
10# linqing171

还有,我写那个systick只是个形式,其实我完全可以去掉不写那个

使用特权

评论回复
linqing171| | 2010-5-5 23:32 | 显示全部楼层
楼主还没有看明白我的回复?
while 1 一直在循环 STR       R0,[R1] 这一句就是你说的被优化那句,其实没有被优化。

这里的R1 就是 (volatile ulong *)0x50004000

中断函数里面的R0 也是(volatile ulong *)0x50004000

中断函数里面 ++ *R0 有代码,主程序里 *R1= 常数(保存在R0)也有汇编代码。

请问那句被优化了?

只要是你有调用,它就会给你编译出把r0压栈出栈的代码。

使用特权

评论回复
David_ming|  楼主 | 2010-5-6 13:10 | 显示全部楼层
KEIL的态度很好,一直在跟进

使用特权

评论回复
goldany| | 2010-5-6 22:55 | 显示全部楼层
被优化的原因是编译器的问题,看看配置。

使用特权

评论回复
bit6019| | 2010-5-8 15:03 | 显示全部楼层
就是,好好检查下你配置好没

使用特权

评论回复
思行合一| | 2010-6-28 21:56 | 显示全部楼层
不知道楼主现在解决没?怎么解决的?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名::“哥洒脱如此”

22

主题

762

帖子

2

粉丝