STVD+Cosmic4.3.4常数取“~”问题!谢谢!

fifthspace   2010-6-14 19:07 楼主
tmp = ~0x01;   //编译及执行结果是正确的,
WDR();

if ( tmp == ~0x01) //编辑及执行结果是错误的,看下面汇编,为什么比较的时候不支持“~”呢?有那位可以讲解一下,谢谢!
{
  WDR();
}

WDR();




main.c:44  WDR();
0x8fe0 <main+4>             0x35AA50E0      MOV   0x50e0,#0xaa        MOV   _IWDG_KR,#0xaa
main.c:46  tmp = ~0x01;
0x8fe4 <main+8>             0xA6FE          LD    A,#0xfe             LD    A,#0xfe
0x8fe6 <main+10>            0x6B01          LD    (0x01,SP),A         LD    (0x01,SP),A
main.c:47  WDR();
0x8fe8 <main+12>            0x35AA50E0      MOV   0x50e0,#0xaa        MOV   _IWDG_KR,#0xaa
main.c:49  if ( tmp == ~0x01)
0x8fec <main+16>            0x7B01          LD    A,(0x01,SP)         LD    A,(0x01,SP)
main.c:54  WDR();
0x8fee <main+18>            0x35AA50E0      MOV   0x50e0,#0xaa        MOV   _IWDG_KR,#0xaa

回复评论 (23)

tmp = ~0x01;
        WDR();
       
        if ( tmp == 0xfe)    //去掉“~”这样写编译执行就正常,头晕!
        {
                WDR();
        }
       
        WDR();

main.c:44                WDR();
0x8fe0 <main+4>             0x35AA50E0      MOV   0x50e0,#0xaa        MOV   _IWDG_KR,#0xaa
main.c:46                tmp = ~0x01;
0x8fe4 <main+8>             0xA6FE          LD    A,#0xfe             LD    A,#0xfe
0x8fe6 <main+10>            0x6B01          LD    (0x01,SP),A         LD    (0x01,SP),A
main.c:47                WDR();
0x8fe8 <main+12>            0x35AA50E0      MOV   0x50e0,#0xaa        MOV   _IWDG_KR,#0xaa
main.c:49                if ( tmp == 0xfe)
0x8fec <main+16>            0x7B01          LD    A,(0x01,SP)         LD    A,(0x01,SP)
0x8fee <main+18>            0xA1FE          CP    A,#0xfe             CP    A,#0xfe
0x8ff0 <main+20>            0x2604          JRNE  0x8ff6              JRNE  0x8ff6
main.c:51                        WDR();
0x8ff2 <main+22>            0x35AA50E0      MOV   0x50e0,#0xaa        MOV   _IWDG_KR,#0xaa
main.c:54                WDR();
0x8ff6 <main+26>            0x35AA50E0      MOV   0x50e0,#0xaa        MOV   _IWDG_KR,#0xaa
点赞  2010-6-14 19:10
                                 这个软件的地雷太多了!
点赞  2010-6-14 19:12
                                 学习了
点赞  2010-6-14 19:17
改成 int tmp;
~0x01结果是(int)0XFFFE,而不是0xFE。
(此处缘由庆参考C语言标准关于~运算符号的描述)

如果tmp是八位数,
if ( tmp == ~0x01)  恒不成立。
点赞  2010-6-14 19:17
改成INT还是错:

main.c:44                WDR();         
0x8fe0 <main+4>             0x35AA50E0      MOV   0x50e0,#0xaa        MOV   _IWDG_KR,#0xaa
main.c:46                tmp = ~0x0001;
0x8fe4 <main+8>             0xAEFFFE        LDW   X,#0xfffe           LDW   X,#0xfffe
0x8fe7 <main+11>            0x1F01          LDW   (0x01,SP),X         LDW   (0x01,SP),X
main.c:48                WDR();
0x8fe9 <main+13>            0x35AA50E0      MOV   0x50e0,#0xaa        MOV   _IWDG_KR,#0xaa
main.c:50                if ( tmp == ~0x0001)
0x8fed <main+17>            0x1E01          LDW   X,(0x01,SP)         LDW   X,(0x01,SP)
main.c:55                WDR();
0x8fef <main+19>            0x35AA50E0      MOV   0x50e0,#0xaa        MOV   _IWDG_KR,#0xaa
点赞  2010-6-14 19:28
只要加了“~”
编译结果就只有一句话了:
main.c:50                if ( tmp == ~0x0001)
0x8fed <main+17>            0x1E01          LDW   X,(0x01,SP)         LDW   X,(0x01,SP)

后面的比较语句就没有了:
0x8fee <main+18>            0xA1FE          CP    A,#0xfe             CP    A,#0xfe
0x8ff0 <main+20>            0x2604          JRNE  0x8ff6              JRNE  0x8ff6
少了这两句!
点赞  2010-6-14 19:30
谢谢“voidx”!刚才查了一下,标准C确实是16位的:

4. 求反运算 求反运算符~为单目运算符,具有右结合性。 其功能是对参与运算的数的各二进位按位求反。例如~9的运算为: ~(0000000000001001)结果为:1111111111110110

不过以前用AVR的时候都是这么写的,都正常!现在16位8位都试了,结果一样,那应该跟位数没关系了!
就目前情况来看估计就是编译器的地雷了!用Cosmic是越深入心理越发虚啊!唉!就这样的效果还要2多万元!!!我买CVAVR时才花了一千多元,还没出过这么低级的错误!
点赞  2010-6-14 19:43
                                 确实啊
点赞  2010-6-14 20:28
编译器我都用IAR。
IAR相对来说,语言还是比较标准的。

IARSTM8才出第一版,效率比Cosmic略差。
不多相信IAR后续版本效率超Cosmic不是难事。
点赞  2010-6-14 20:50
                                 实在不行也只能这样了!
点赞  2010-6-14 20:58
这个还真不能怪编译器,这本来就是程序没写好嘛:

int main(int argc,char *argv[])
{
    uint8   tmp = ~1;

    if(tmp == ~1){
        tmp += 1;
    }
}

编译器警告:src\user\main.c(111): warning:  #514-D: pointless comparison of unsigned integer with a negative constant
点赞  2010-6-15 08:35
发现comsic确实存在问题。

==比较,未按照标准C要求进行提升。

实例1:
int main()
{       
         int  temp;       
        temp=~0x01;       
        if(temp==~0x01)
        {
                _asm("nop");
        }               
        while (1);
}
结果:if(temp==~0x01)为真,这里正确。
~0x01的值是(int)0xfffe,即-2。
(int)-2==(int)-2,结果为真。

实例2:

int main()
{       
        unsigned int  temp;       
        temp=~0x01;       
        if(temp==~0x01)
        {
              _asm("nop");
        }       
        while (1);
}

结果:comsic为假,iarstm8为真。
temp为unsigned int类型,temp=~0x01后,temp的值为0xFFFE,
(unsigned int)0xFFFE==(int)(-2)应该为真,
原因是int与unsigned int比较,int要提升至unsigned int,
即:(unsigned int)0xFFFE==(unsigned int)((int)(-2))为真。
iar,avrgcc都是正确的。

实例3:
int main()
{
       if((unsigned int)(-2)==(-2))   
       {
                     _asm("nop");  
        }       
      while (1);
}
结果comsic为假,iarstm8,avrgcc为真。
原因同上。
点赞  2010-6-15 09:51
                                 看来得小心了
点赞  2010-6-15 10:39
                                 难用的单片机加上难用的编译器。。。。
点赞  2010-6-15 11:00
刚刚全部试了,现在已经明白了,谢谢voidx,hgjinwei!
原因如下:编译器在作比较时的对于常数取“~”当有 “ 符号 ” 的 “int” 类型所以,如果变量定义的不是
“int” 则需要用强制类型转换才能正确执行!

(相应数据类型)~0x01 这样就正确了!
比如:(unsigned char)~0x01这样子写就正确!
再次感谢各位的解答!
点赞  2010-6-15 14:35
                                 好垃圾的编译器。。好垃圾的寄存器分布啊。。又不得不用。。
点赞  2010-6-15 19:52
                                  AVR没货没关法!
点赞  2010-6-15 22:27
还是用AIR吧
不要跟不上
点赞  2010-6-15 22:29
                                 照楼主那么说,编译器确实非常糟糕
点赞  2010-6-16 19:13
12下一页
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复