This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Bitwise logical AND stores in a bit ....

Hi,

I get a curious result when compiling such a following code :

typedef union  {

  unsigned char                cCtrlFullByte;

  struct {
    unsigned char  bEnable          : 1;
    unsigned char  cUnused          : 7;

  }  cCtrlStruct;
} CtrlUnion;

void main (void)  {

    unsigned char  dummy = 0x55;
    CtrlUnion  xdata    bitUnion;

    bitUnion.cCtrlStruct.bEnable = dummy & 0x40;

    return;
}


It results in :
MOV A,#0x55
ANL A,#0x00
MOV R7,A
MOV DPTR, #0x0000
MOVX A,@DPTR
ANL A,#0xFE
ORL A,R7
MOVX @DPTR, A 

I thought that the bit result of bitwise logical AND is 1 if result is not 0, else 0.
It seems that I didn't understand ANSI the same way than Keil compiler ? Am I wrong ?

Arnaud DELEULE

Parents
  • Why not, but how do you explain a different casting rule when the destination is a "real bit"

    void main (void)  {
      unsigned char  dummy = 0x55;
      bit   bitValue;
    
      bitValue = dummy & 0x40;
    
      return;
    }
    
    It results in :
    MOV A,#0x55
    MOV C, 0xE0.6
    MOV 0x20.0, C
    
    Now if destination is a bit, the cast considers that the result is the 6th bit (mask with 0x40).

    Why different casting rules occurs for a similar destination format (1-bit wide) ?

    Moreover, in the above "C" code, if the 0x40 mask is replaced by multibyte mask (like 0x44)
    the result is 0 if no bit match the mask and 1 if there is at least one :
    MOV A,#0x55
    ANL A,#0x44
    ADD A,#0xFF
    MOV 0x20.0, C
    


    This is very confusing....and should be checked each time ...

    Cheers

    Arnaud

Reply
  • Why not, but how do you explain a different casting rule when the destination is a "real bit"

    void main (void)  {
      unsigned char  dummy = 0x55;
      bit   bitValue;
    
      bitValue = dummy & 0x40;
    
      return;
    }
    
    It results in :
    MOV A,#0x55
    MOV C, 0xE0.6
    MOV 0x20.0, C
    
    Now if destination is a bit, the cast considers that the result is the 6th bit (mask with 0x40).

    Why different casting rules occurs for a similar destination format (1-bit wide) ?

    Moreover, in the above "C" code, if the 0x40 mask is replaced by multibyte mask (like 0x44)
    the result is 0 if no bit match the mask and 1 if there is at least one :
    MOV A,#0x55
    ANL A,#0x44
    ADD A,#0xFF
    MOV 0x20.0, C
    


    This is very confusing....and should be checked each time ...

    Cheers

    Arnaud

Children
  • The bit type is a specific Keil extension, so they can implement it in the most efficient, target-specific way they can think of - without having to worry about any other ANSI constraints;
    Bitfields, on the other hand, are standard ANSI - so Keil may well be constrained in their implementation (and implementations of bitfields are notorious for being inefficient!)

    BTW: Have you disabled the defualt ANSI Integer Promotions?

  • > The bit type is a specific Keil extension,
    > so they can implement it in the most efficient,
    > target-specific way they can think of - without
    > having to worry about any other ANSI constraints;

    Why not, but it is not a reason to have opposite result when using
    a bit type or a bit in bit-field type !!!

    > Bitfields, on the other hand, are standard ANSI
    > - so Keil may well be constrained in their
    > implementation (and implementations of bitfields
    > are notorious for being inefficient!)

    My problem is not efficiency but COHERENCY of the compiled code !
    If I used a bit-field type stored in BDATA, or a byte with sbit declarations, the result will be different !!!
    So, if you write your code using Keil bit type, the result will be good, whereas using bit-field type (for portability), the result will be false !!!

    Not really coherent ! ;-(

    Is that a compiler bug or a normal issue ?

    > BTW: Have you disabled the defualt ANSI Integer Promotions?
    Obviously Yes, but no change.


    Arnaud DELEULE



  • The code in Araund's example is correct. The first example where C is set from E0.6 (actually Accumulator bit 6 .. E0 is the ACC sfr) is exactly the value specified.

    In the second example, the and with 0x44 and add 0xff sets carry if either of the two bits in the mask are non-zero.

    Looks to me like the compiler did exactly as it should.

  • You're right.
    It does exactly what it should when the destination is a Keil "bit" type.
    If the type of the destination is a 1-bit wide field in a bit-field structure,
    the result will be different.

    For me, that should not happen.

    Regards

    Arnaud