We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
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; }
MOV A,#0x55 ANL A,#0x00 MOV R7,A MOV DPTR, #0x0000 MOVX A,@DPTR ANL A,#0xFE ORL A,R7 MOVX @DPTR, A
Arnaud, the compiler is generating correct code. You are casting from an 8-bit unsigned char to a 1-bit unsigned char. The rule when casting from a large unsigned type to a smaller unsigned type of variable is simply to discard the most significant bits. You will find that the same sort of thing happens when you cast from an unsigned int to an unsigned char – the 8 most significant bits of the unsigned int are discarded. Norbert is quite correct to say that bit memory and and a 1-bit bit field are not the same thing. In C you have to be vary careful with Booleans – only logical operators and some functions return truly Boolean results. However:
bit xdata externalBit; /*why not?*/
typedef struct { unsigned char bEnable : 1; unsigned char cUnused : 7; } BitFieldStruct; unsigned char dummy = 0x55; BitFieldStruct bdata bitUnion; void main (void) { bitUnion.bEnable = dummy & 0x74; return; }
0000 900000 R MOV DPTR,#dummy 0003 E0 MOVX A,@DPTR 0004 5400 ANL A,#00H 0006 FF MOV R7,A 0007 E500 R MOV A,bitUnion 0009 54FE ANL A,#0FEH 000B 4F ORL A,R7 000C F500 R MOV bitUnion,A 000E ?C0085: 000E 22 RET
…. unsigned char dummy = 0x55; BitFieldStruct bdata bitUnion; void main (void) { bitUnion.bEnable = dummy & 0x71; return; }
0000 900000 R MOV DPTR,#dummy 0003 E0 MOVX A,@DPTR 0004 5401 ANL A,#01H 0006 FF MOV R7,A 0007 E500 R MOV A,bitUnion 0009 54FE ANL A,#0FEH 000B 4F ORL A,R7 000C F500 R MOV bitUnion,A 000E ?C0085: 000E 22 RET
typedef struct { boolean bEnable : 1; unsigned char cUnused : 7; } BitFieldStruct; unsigned char dummy = 0x55; BitFieldStruct bdata bitUnion; void main (void) { bitUnion.bEnable = ( dummy & 0x74 ) != 0; return; }
0000 900000 R MOV DPTR,#dummy 0003 E0 MOVX A,@DPTR 0004 5474 ANL A,#074H 0006 6004 JZ ?C0085 0008 7F01 MOV R7,#01H 000A 8002 SJMP ?C0086 000C ?C0085: 000C 7F00 MOV R7,#00H 000E ?C0086: 000E EF MOV A,R7 000F 5401 ANL A,#01H 0011 FF MOV R7,A 0012 E500 R MOV A,bitUnion 0014 54FE ANL A,#0FEH 0016 4F ORL A,R7 0017 F500 R MOV bitUnion,A 0019 ?C0087: 0019 22 RET
0000 900000 R MOV DPTR,#dummy 0003 E0 MOVX A,@DPTR 0004 5474 ANL A,#074H 0006 6004 ADD A,#FFH 0012 E500 R MOV A,bitUnion 0014 54FE MOV Acc.0,C 0017 F500 R MOV bitUnion,A 0019 ?C0087: 0019 22
OK, I understand the thought process but I guess that very few people do 1-bit arithmetic. But that the way Keil choose and it is one solution. Not the way for me, but that's the life ! ;-) Thanks all for your help and explanations Arnaud