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

??

  • I am not sure that I really understand your question, but I hope that this helps.

    In general, when you write a C statement that includes arithmetic operations multiply, divide and modulo where one operand is a constant that is 2^n, the Keil compiler is good at converting the operation to the shift, SWAP and mask equivalent. In most cases, the programmer is best advised to use the operators that make the best sense to a human reader and leave the rest to the compiler.

    You cannot tell the compiler to do things any particular way. The only alternative is to resort to assembly language...

    It is possible to achieve shift operations by multiplying or dividing. In cases when the number of bits to shift is variable, this can work out faster than bit shifting. To shift n bits to the left or right, multiply or divide by 2^n.

    When shifting by a variable number of bits, Keil C51 does not do so well. Keil also offers some some "intrinsic" functions for doing rolls, these are not efficient when shifting for more than about 3 bits. In both these cases, some hand optimisation may be worthwhile.

    This is particularly true when rolling long variables. See:

    http://www.keil.com/forum/docs/thread1252.asp

    for an example. The methods used in the example can easily be adapted to provide solutions that shift or roll, longs, ints or chars.

  • 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

  • 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.