MDK赋值出错的BUG

//=====================================================================
//TITLE:
//    MDK赋值出错的BUG
//AUTHOR:
//    norains
//DATE:
//    Friday  15-April-2011
//Environment:
//    MDK 4.02
//=====================================================================

 

    在我们看这BUG之前,先看一个很简单的算式:0x81 & 0x7F = ? 估计很多人都会知道,结果等于1。如果对此还有点懵懂的朋友,可以用windows自带的计算器试试,结果也是1。但这算式,如果是在MDK,那么可能就不同了,结果很可能不是1,如图:

MDK赋值出错的BUG_第1张图片


    从图中可以看到,ep->bEndpointAddress数值为0x81,和0x7F进行与操作后,结果保存到endpointNum,却发现结果变成了0x68!这究竟是怎么一回事呢?

 

    在详细说明这问题之前,我们将"endpointNum = ep->bEndpointAddress & 0x7F"这行代码分解为两个步骤,如下所示:
    endpointNum = ep->bEndpointAddress; endpointNum &= 0x7F;

 

    接着我们重新编译,在编译器中查看相应的结果,如图所示:

MDK赋值出错的BUG_第2张图片


    我们可以很明显看到,"endpointNum = ep->bEndpointAddress"会被汇编成如下两条语句:
MOVS r0,r0 LDRB r6,{r0,#0x02}

 

    r6是endpointNum变量的地址,这个没问题。问题就出在,r0的数值。在执行MOVS操作之前,r0为0x00000001,然后在这个地址上偏移2个byte地址所对应的数值赋值给r6!这很明显是不对的,因为r0的数值应该等于ep的地址,也就是0x20009D60才对!也难怪乎会出错了。

 

    这个应该是MDK编译器的BUG。那么,我们有没有办法避开这个BUG呢?方法还是有的,只要在赋值语句之前随便初始化一个变量即可,比如增加这么一个语句:"int iDumy = 0",执行的结果如下图所示:

MDK赋值出错的BUG_第3张图片


    此时我们发现,赋值语句的汇编代码已经改变,变为:
LDR r0,{sp,#0x04} LDRB r6,{r0,#0x02}

 

    改变的最直接结果就是,r0寄存器的数值刚好是ep指针的地址,不再是那个可恶的0x00000001,于是endpointNum就变成了正确的0x81,也就意味着我们成功绕开了MDK这个莫名其妙的bug!
 

你可能感兴趣的:(windows,汇编,byte,编译器)