打印

出大事了,KEIL编译错了???

[复制链接]
4229|23
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wsl_5631|  楼主 | 2009-7-28 20:48 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
                         case CSL:
            switch(key)
            {
                case KENTER:
                    single_weight = 0;
                    display_weight();
                    status = WORK;
                    key_sound();
                    break;
                case KSET:
                    point = 0;    
                    display_sap();            
                    status = SETL_SAPN;                

--------------------------------------------------------------------

                 case PERCENT_CSL:
            switch(key)
            {
                case KENTER:
                    percent_weight = 0;
                    display_weight();            
                    status = WORK;
                    key_sound();
                    break;

****************************************************

  case CSL:
    switch(key)
    {
    case KENTER:
       single_weight = 0;
       display_weight();
       status = WORK;
       key_sound();
       break;
反汇编如下:
 019B:         MOV  R0,#87H
 019D:         LCALL 0FE0H
 01A0:         AJMP   0267H

....
 0FE0H:      POP  DPH
             POP  DPL
             CLR  A
             MOVC  A,@A+DPTR
             MOV @R0,A
             INC  R0
             MOV  A,#01H
        MOVC  A,@A+DPTR
             MOV @R0,A
             INC  R0
        MOV  A,#02H
        MOVC  A,@A+DPTR
             MOV @R0,A
             INC  R0
        MOV  A,#03H
        MOVC  A,@A+DPTR
             MOV @R0,A
             MOV  A,#04H
        JMP  A,@A+DPTR



case PERCENT_CSL:
    switch(key)
    {
     case KENTER:
        percent_weight = 0;
             display_weight();            
        status = WORK;
       key_sound();

反汇编如下:
 0262:         MOV  R0,#C8H
 0264:         LCALL 0FF9H
 0267:         NOP
               NOP
               NOP
               NOP
              ......
0FF9H:       POP  DPH
             POP  DPL
             CLR  A
             MOVC  A,@A+DPTR
             MOVX @R0,A
             INC  R0
             MOV  A,#01H
        MOVC  A,@A+DPTR
             MOVX @R0,A
             INC  R0
        MOV  A,#02H
        MOVC  A,@A+DPTR
             MOVX @R0,A
             INC  R0
        MOV  A,#03H
        MOVC  A,@A+DPTR
             MOVX @R0,A
             MOV  A,#04H
        JMP  A,@A+DPTR

问题:
single_weight = 0;
反汇编用LCALL 0FE0H 实现,通过查表赋值,用POP DPH  POP DPL 
弹出查表地址,01A0后面应该放表格 NOP NOP NOP NOP (0,0,0,0)

由于同0267处放的表格一样,表格后面的程序也一样,程序用AJMP   0267H
直接跳过去了,结果造成POP DPH, POP DPL弹出的不是表格地址,程序运行出错。 

我这样理解对吗,望高手指点。 有点长,请大家耐心看完。谢谢


相关帖子

沙发
ayb_ice| | 2009-7-28 21:01 | 只看该作者

我没有看,但肯定没有错

因为我相信KEIL,同时你都没有去调试验证,就发发彪

使用特权

评论回复
板凳
wsl_5631|  楼主 | 2009-7-29 08:18 | 只看该作者

谢谢

我也觉得KEIL应该不会错,但调试的确出错了,所以我才去查反汇编。如果没错的话,谁能帮我解释一下这反汇编是怎么回事,有时间,请高手帮忙看一下。

使用特权

评论回复
地板
mohanwei| | 2009-7-29 08:50 | 只看该作者

贴一下完整的片断,别少了几个break或者多了几个分号

使用特权

评论回复
5
有风| | 2009-7-29 08:53 | 只看该作者

Re

switch后面,又case,
还不如
switch(condition)   // condition == key && condition1
{
}

使用特权

评论回复
6
冷漠| | 2009-7-29 09:45 | 只看该作者

经验:全是优化惹的祸。

别让编译器太聪明。

降低C51优化级别,降到0试试。

使用特权

评论回复
7
wsl_5631|  楼主 | 2009-7-29 10:00 | 只看该作者

谢谢

re 5楼 switch 语句嵌套应该没问题吧

re 6楼: 经验:全是优化惹的祸。? 优化会使编译出错吗,我用的是9级优化
#pragma        ot(9,speed)  我想改为0级试试,代码太大,有一对警告,连接不成功。 我想问一下,优化等级过高会不会出错,大家一般用几级优化。

使用特权

评论回复
8
huangqi412| | 2009-7-29 10:34 | 只看该作者

C语言中多用大括号比较容易看,也比较保险...

先降低优化试试

使用特权

评论回复
9
emailli| | 2009-7-29 10:36 | 只看该作者

优化惹得祸,不代表是错哦!

如果你的程序压根就不会出现其中一个CASE,那么那个CASE就会被优化掉。

或者你的程序在不同的CASE下的操作实际上是一样的。

优化的时候也会将其合并。

大部分情况不会出问题。

在一些极其特殊的时候可能出问题。

如果你在switch内单步调试,可能觉得跳转是错的。

但是,如果你在switch外单步调试,你又可以得到正确的结果的。

使用特权

评论回复
10
古道热肠| | 2009-7-29 10:43 | 只看该作者

错没错,看结果

优化后,程序走向会不如您所想象的走.

使用特权

评论回复
11
icecut| | 2009-7-29 10:58 | 只看该作者

keil的错误遇到过.

建议用高版本....

自己查汇编.不对就换写法

使用特权

评论回复
12
xwj| | 2009-7-29 11:43 | 只看该作者

对于LZ这样的乱糟糟的程序,我更愿意相信keil

使用特权

评论回复
13
wsl_5631|  楼主 | 2009-7-29 12:22 | 只看该作者

无论是单步,还是全速,结果的确是错了

             case CSL:
            switch(key)
            {
                case KENTER:
                    single_weight = 0;
                    display_weight();
                    status = WORK;
                    key_sound();
                    break;
                case KSET:
                    point = 0;    
                    display_sap();            
                    status = SETL_SAPN;    
                    key_sound();
                    break;
                    
程序进入分支case KENTER: 后
                    single_weight = 0;后面的程序没有被执行,执行single_weight = 0;是调用LCALL 0FE0H 返回时发生错误, 
返回到
case KSET:
                    point = 0;    
                    display_sap();            
                    status = SETL_SAPN;    
                    key_sound();
                    break;
的  status = SETL_SAPN;  往下执行。
                    

                     

  


使用特权

评论回复
14
wsl_5631|  楼主 | 2009-7-29 12:26 | 只看该作者

我的程序总体上是不规范的

我的程序总体上是不规范的,比较乱,但这几句感觉不出乱啊,应该是看的懂的吧

使用特权

评论回复
15
wsl_5631|  楼主 | 2009-7-29 12:57 | 只看该作者

刚刚写了一个测试程序,证明是KEIL优化有问题


刚刚写了一个测试程序,证明是KEIL优化有问题。
下面的一个程序不需要硬件,可以直接模拟仿真,有兴趣的可以试一下。
程序进入key_prcocess---->switch(status)--->case WORK: ---->switch(key)---->case 1: data_var = 0;  后出错,会执行到delay5us();
                    status = IDLE;
                    while(1);
                    break;




#include"STC89C58RD+.H"
#include<stdlib.h>

#define        uchar            unsigned char
#define        ulint            unsigned long int

#pragma ot(9,speed)                //9级优化

#define        BUZZER            P1_0


#define        WORK        0
#define        SET            1
#define        IDLE        2


idata    ulint      data_var;
idata    ulint      idata_var;
xdata    ulint      xdata_var;


data    uchar      status;



void    key_process(uchar key);
void    delay5us();
void    delay5ms();




void    main()
{
        while(1)
        {
             status = WORK;
            key_process(1);
        }
}
    
void    key_process(uchar key)
{
    switch(status)
    {
        case WORK:
            switch(key)
            {
                case 1:
                    data_var = 0;
                    delay5us();
                    BUZZER = 1;
                    delay5ms();
                    BUZZER = 0;
                    status = IDLE;
                    break;
                case 2:
                    data_var = 0;
                    delay5ms();
                    delay5us();
                    status = IDLE;
                    while(1);
                    break;
                default:
                    break;
            }
            break;
        case SET:
            switch(key)
            {
                case 1:
                    xdata_var = 0;
                    delay5us();
                    BUZZER = 1;
                    delay5ms();
                    BUZZER = 0;
                    status = IDLE;;
                    break;
                case 2:
                    idata_var = 0x897890;
                    delay5us();
                    BUZZER = 0;
                    delay5ms();
                    BUZZER = 1;
                    status = IDLE;
                    break;
                default:
                    break;
            }
            break;
        case IDLE:
            break;
        default:
            break;
    }
}
void    delay5us()
{
    uchar i;
    for(i=0;i<5;i++);
}
void    delay5ms()
{
    uchar i;
    for(i=0;i<50;i++)delay5us();
}






使用特权

评论回复
16
bhsdlmj| | 2009-7-29 13:37 | 只看该作者

估计是程序写的不太规范导致出了问题!

使用特权

评论回复
17
mohanwei| | 2009-7-29 14:44 | 只看该作者

15楼的代码不规范,switch里有死循环

也就是以下这段代码的倒数第二行:“while(1);”
void    key_process(uchar key)
{
    switch(status)
    {
        case WORK:
            switch(key)
            {
                case 1:
                    data_var = 0;
                    delay5us();
                    BUZZER = 1;
                    delay5ms();
                    BUZZER = 0;
                    status = IDLE;
                    break;
                case 2:
                    data_var = 0;
                    delay5ms();
                    delay5us();
                    status = IDLE;
                    while(1);
                    break;

上面代码中,case 1和case 2部分代码是相同的,所以优化的时候被合并了。单步调试的时候可以看到,进入case 1中执行了“data_var = 0;”后就跳到了case 2……但是Keil没想到还有这么变态的用户,居然在switch里挖了个陷阱,结果一进case 2就出不来了。

使用特权

评论回复
18
mohanwei| | 2009-7-29 14:53 | 只看该作者

优化是有前提的,只有符合规范的程序才能优化

不符合规范的随便优化基本上必死无疑。

使用特权

评论回复
19
wsl_5631|  楼主 | 2009-7-29 17:33 | 只看该作者

re 17楼

re 17楼
while(1)是我测试用的,实际上,如果两部分程序相同,但其中一部分程序有while(1),另一部分没有,KEIL绝对不会用跳转优化。

case 1和case 2部分代码是相同的?

case 1 和 case 2 的代码根本是不同的,看一下反汇编就知道了,KEIL并没有把它优化跳到有while(1),case 2 ,而是跳到case SET 分支的 case 2了。之所以出错,是KEIL把表格当代码优化了。




使用特权

评论回复
20
wsl_5631|  楼主 | 2009-7-29 17:52 | 只看该作者

把程序修改一下,再贴



                    _nop_();
                    _nop_();
                    while(1);





#include"STC89C58RD+.H"
#include<stdlib.h>
#include<intrins.h>

#define        uchar            unsigned char
#define        ulint            unsigned long int

#pragma ot(9,speed)                //9级优化

#define        BUZZER            P1_0


#define        WORK        0
#define        SET            1
#define        IDLE        2


idata    ulint      data_var;
idata    ulint      idata_var;
xdata    ulint      xdata_var;


data    uchar      status;



void    key_process(uchar key);
void    delay5us();
void    delay5ms();




void    main()
{
        while(1)
        {
             status = WORK;
            key_process(1);
        }
}
    
void    key_process(uchar key)
{
    switch(status)
    {
        case WORK:
            switch(key)
            {
                case 1:
                    data_var = 0;
                    delay5us();
                    BUZZER = 1;
                    delay5ms();
                    BUZZER = 0;
                    status = IDLE;
                    break;
                case 2:
                    _nop_();
                    _nop_();
                    _nop_();
                    _nop_();
                    _nop_();
                    while(1);
                    break;
                default:
                    break;
            }
            break;
        case SET:
            switch(key)
            {
                case 1:
                    xdata_var = 0;
                    delay5us();
                    BUZZER = 1;
                    delay5ms();
                    BUZZER = 0;
                    status = IDLE;;
                    break;
                case 2:
                    idata_var = 0x897890;
                    delay5us();
                    BUZZER = 0;
                    delay5ms();
                    BUZZER = 1;
                    status = IDLE;
                    break;
                default:
                    break;
            }
            break;
        case IDLE:
            break;
        default:
            break;
    }
}
void    delay5us()
{
    uchar i;
    for(i=0;i<5;i++);
}
void    delay5ms()
{
    uchar i;
    for(i=0;i<50;i++)delay5us();
}



使用特权

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

本版积分规则

43

主题

335

帖子

2

粉丝