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

shift with ">>" in c51 ...

some time c user do shift for mul and divide and some time u write byte to byte
then not require any carry for me in asm i do two shift mul 4

i do it with c51

ypos3 = ypos>>3;
; SOURCE LINE # 237
MOV A,R5
RRC A
RRC A
ANL A,#01FH
;---- Variable 'ypos3?1255' assigned to

HOW DO IT IN C51 WITHOUT
MOV A,R5
ANL A,#01FH

??

Parents
  • Hi,

    the main reason for the ANL A,01Fh is simply, that RRC shifts the carry bit into the accu MSB.
    So after 3 RRC you have the 3 MSBs set to some "random" value, which is NOT what the C-statement meant.
    The MOV A,R5 is necessary, because the 8051 can just shift the accu (and not some register).

    If you're using assembler, ANY shift can be done in TWO statements (plus the ANL), provided, data is stored in the accu already.


    bis die Tage...
    Mathias

Reply
  • Hi,

    the main reason for the ANL A,01Fh is simply, that RRC shifts the carry bit into the accu MSB.
    So after 3 RRC you have the 3 MSBs set to some "random" value, which is NOT what the C-statement meant.
    The MOV A,R5 is necessary, because the 8051 can just shift the accu (and not some register).

    If you're using assembler, ANY shift can be done in TWO statements (plus the ANL), provided, data is stored in the accu already.


    bis die Tage...
    Mathias

Children
  • For this C code:

    unsigned char t;
    ...
    
        t = t << 3;
    
        t = _crol_(t,3);
    
    Keil C51 (6.14) will give you this:
                                               ; SOURCE LINE # 988
                                               ; SOURCE LINE # 991
    0005 900000      R     MOV     DPTR,#t
    0008 E0                MOVX    A,@DPTR
    0009 FF                MOV     R7,A
    000A 33                RLC     A
    000B 33                RLC     A
    000C 33                RLC     A
    000D 54F8              ANL     A,#0F8H
    000F FF                MOV     R7,A
    0010 F0                MOVX    @DPTR,A
                                               ; SOURCE LINE # 993
    0011 7803              MOV     R0,#03H
    0013 08                INC     R0
    0014 8001              SJMP    ?C0090
    0016         ?C0089:
    0016 23                RL      A
    0017         ?C0090:
    0017 D8FD              DJNZ    R0,?C0089
    0019 900000      R     MOV     DPTR,#t
    001C F0                MOVX    @DPTR,A
    
    But Mathias is quite right to point out that a single byte in the accumulator can be rotated by any number of bits with no more than TWO instructions.

    To rotate n bits to the left:
    n%8
    0    NOP
    1    RL A
    2    RL A,     RL A
    3    SWAP Acc, RR A
    4    SWAP Acc
    5    SWAP Acc, RL A
    6    RR A,     RR A
    7    RR A
    
    A final masking operation will convert a rotate into a shift operation.

    Keil users might be under the impression that the intrinsic functions are fast and/or compact - they are a little better than a portable C-based algorithm, but they not optimal. Shifting or rolling by a constant number of bits are common operations, sometimes used to achieve fast multiplication or division by 2^n. Shifts and rolls by exactly one bit are common operations required for CRCs, LFSR etc. It really would be nice if the C51 optimiser could do a better job in this area.