打印
[STM8]

STVD+Cosmic 4.3.4 常数取“~”问题!谢谢!

[复制链接]
5894|23
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zcxhe|  楼主 | 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
沙发
zcxhe|  楼主 | 2010-6-14 19:10 | 只看该作者
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

使用特权

评论回复
板凳
zcxhe|  楼主 | 2010-6-14 19:12 | 只看该作者
这个软件的地雷太多了!

使用特权

评论回复
地板
kinso| | 2010-6-14 19:17 | 只看该作者
学习了

使用特权

评论回复
5
voidx| | 2010-6-14 19:17 | 只看该作者
改成 int tmp;
~0x01结果是(int)0XFFFE,而不是0xFE。
(此处缘由庆参考C语言标准关于~运算符号的描述)

如果tmp是八位数,
if ( tmp == ~0x01)  恒不成立。

使用特权

评论回复
6
zcxhe|  楼主 | 2010-6-14 19:28 | 只看该作者
改成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

使用特权

评论回复
7
zcxhe|  楼主 | 2010-6-14 19:30 | 只看该作者
只要加了“~”
编译结果就只有一句话了:
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
少了这两句!

使用特权

评论回复
8
zcxhe|  楼主 | 2010-6-14 19:43 | 只看该作者
谢谢“voidx”!刚才查了一下,标准C确实是16位的:

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

不过以前用AVR的时候都是这么写的,都正常!现在16位8位都试了,结果一样,那应该跟位数没关系了!
就目前情况来看估计就是编译器的地雷了!用Cosmic是越深入心理越发虚啊!唉!就这样的效果还要2多万元!!!我买CVAVR时才花了一千多元,还没出过这么低级的错误!

使用特权

评论回复
9
suzhejun| | 2010-6-14 20:28 | 只看该作者
确实啊

使用特权

评论回复
10
voidx| | 2010-6-14 20:50 | 只看该作者
编译器我都用IAR。
IAR相对来说,语言还是比较标准的。

IARSTM8才出第一版,效率比Cosmic略差。
不多相信IAR后续版本效率超Cosmic不是难事。

使用特权

评论回复
11
zcxhe|  楼主 | 2010-6-14 20:58 | 只看该作者
实在不行也只能这样了!:lol

使用特权

评论回复
12
hgjinwei| | 2010-6-15 08:35 | 只看该作者
这个还真不能怪编译器,这本来就是程序没写好嘛:

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

使用特权

评论回复
13
voidx| | 2010-6-15 09:51 | 只看该作者
发现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为真。
原因同上。

使用特权

评论回复
14
司徒老鹰| | 2010-6-15 10:39 | 只看该作者
看来得小心了

使用特权

评论回复
15
CoolBird007| | 2010-6-15 11:00 | 只看该作者
难用的单片机加上难用的编译器。。。。

使用特权

评论回复
16
zcxhe|  楼主 | 2010-6-15 14:35 | 只看该作者
刚刚全部试了,现在已经明白了,谢谢voidx,hgjinwei!
原因如下:编译器在作比较时的对于常数取“~”当有 “ 符号 ” 的 “int” 类型所以,如果变量定义的不是
“int” 则需要用强制类型转换才能正确执行!

(相应数据类型)~0x01 这样就正确了!
比如:(unsigned char)~0x01这样子写就正确!
再次感谢各位的解答!

使用特权

评论回复
17
CoolBird007| | 2010-6-15 19:52 | 只看该作者
好垃圾的编译器。。好垃圾的寄存器分布啊。。又不得不用。。

使用特权

评论回复
18
zcxhe|  楼主 | 2010-6-15 22:27 | 只看该作者
:lol AVR没货没关法!

使用特权

评论回复
19
wgggjfg| | 2010-6-15 22:29 | 只看该作者
还是用AIR吧
不要跟不上

使用特权

评论回复
20
秋天落叶| | 2010-6-16 19:13 | 只看该作者
照楼主那么说,编译器确实非常糟糕

使用特权

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

本版积分规则

27

主题

138

帖子

2

粉丝