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

Bug in C51 Version 7.05

Dear all,
I would like someone to confirm this bug:

unsigned long b, d;

unsigned long Round2(unsigned long value)
{
  unsigned long WholePart;
  unsigned char Remainder;

  WholePart = value / 10L;
  Remainder = (unsigned char)(value % 10L);

  if (Remainder > 4)
  {
    WholePart++;
  }

  return (WholePart);
}

void main(void)
{
  b = Round2(456756);
  d = Round2(456751);

  do {} while (1);
}

When I compile the program (Level 7, 80C32), I get the following code for the Round2 function:

             ; FUNCTION _Round2 (BEGIN)
                                           ; SOURCE LINE # 3
0000 8F00        R     MOV     value+03H,R7
0002 8E00        R     MOV     value+02H,R6
0004 8D00        R     MOV     value+01H,R5
0006 8C00        R     MOV     value,R4
                                           ; SOURCE LINE # 4
                                           ; SOURCE LINE # 8
0008 E4                CLR     A
0009 7B0A              MOV     R3,#0AH
000B FA                MOV     R2,A
000C F9                MOV     R1,A
000D F8                MOV     R0,A
000E 120000      E     LCALL   ?C?ULDIV
0011 8F00        R     MOV     WholePart+03H,R7
0013 8E00        R     MOV     WholePart+02H,R6
0015 8D00        R     MOV     WholePart+01H,R5
0017 8C00        R     MOV     WholePart,R4
                                           ; SOURCE LINE # 9
0019 E4                CLR     A
001A 7B0A              MOV     R3,#0AH
001C FA                MOV     R2,A
001D F9                MOV     R1,A
001E F8                MOV     R0,A
001F AF00        R     MOV     R7,value+03H
0021 AE00        R     MOV     R6,value+02H
0023 AD00        R     MOV     R5,value+01H
0025 AC00        R     MOV     R4,value
0027 120000      E     LCALL   ?C?ULDIV
;---- Variable 'Remainder' assigned to Register 'R7' ----
                                           ; SOURCE LINE # 11
002A EB                MOV     A,R3
002B D3                SETB    C
002C 9404              SUBB    A,#04H
002E 4015              JC      ?C0001
                                           ; SOURCE LINE # 12
                                           ; SOURCE LINE # 13
0030 E500        R     MOV     A,WholePart+03H
0032 2401              ADD     A,#01H
0034 F500        R     MOV     WholePart+03H,A
0036 E4                CLR     A
0037 3500        R     ADDC    A,WholePart+02H
0039 F500        R     MOV     WholePart+02H,A
003B E4                CLR     A
003C 3500        R     ADDC    A,WholePart+01H
003E F500        R     MOV     WholePart+01H,A
0040 E4                CLR     A
0041 3500        R     ADDC    A,WholePart
0043 F500        R     MOV     WholePart,A
                                           ; SOURCE LINE # 14
0045         ?C0001:
                                           ; SOURCE LINE # 16
0045 AF00        R     MOV     R7,WholePart+03H
0047 AE00        R     MOV     R6,WholePart+02H
0049 AD00        R     MOV     R5,WholePart+01H
004B AC00        R     MOV     R4,WholePart
                                           ; SOURCE LINE # 17
004D         ?C0002:
004D 22                RET

             ; FUNCTION _Round2 (END)

Notice the result for source line 11, which should be:

002A EB                MOV     A,R7

as the comment just before correctly says.

Thanks in advance,

José Sánchez del Pozo

  • What makes you think that "Remainder" should be in R7?
    I'm not familiar with the implementation of "?C?ULDIV", but it would appear to return the result of the division in R4/R5/R6/R7, and the remeainder in R0/R1/R2/R3, so the LSB of the remainder is in R3, so the assembly code is correct.

    (Although surely the second call to ?C?ULDIV is redundant, as it is fed exactly the same input values. Maybe the (char) cast confused the optimiser.)

  • Richard,
    I wouldn't have noticed it if the compiler didn't specify that Remainder is R7!

    After simulating the program in uVision, it is clear that, either the assignment of R7 to "Remainder", or the code is wrong, because "Remainder" always holds the same value, 107d, whereas the program seems to work correctly.

    Something is definitely wrong there, but now I am not sure what.

    Best regards,

    Jose

  • Richard,
    It seems that you are correct and R3 is indeed the LSB of the remainder in ULDIV, and the programs works fine, but then there is something wrong with the simulator, and/or compiler, because:

    1. The compiler says explicitly that "Remainder" is assigned to R7 and

    2. the simulator is part of the conspiracy, giving 0x6B as the value of "Remainder".

    Any clues?

    Jose

  • The code is just fine. R3 is the remainder LSB after division and it would have been stored in R7 if the compiler had not optimized it out.

    'Remainder' is a local variable that has no further use, why keep it?

    I agree that the compiler could have removed the comment but that may be asking a lot.

  • Why didn't the compiler remove everything between

    ; SOURCE LINE # 9
    and
    ; SOURCE LINE # 11
    as the remainder was already in R3 after the first call to LDIV?

  • I guess the short answer is that the optimiser is not perfect and in this particular case the effort of updating the optimiser does not justify the benefit.

    However, I must admit that this situation does occur in most applications every now and then and it is a pity that there is not a standard library function available to deal with it. In this particular case, it looks as if it might be quite straightforward to generate your own assembly language function that makes use of a single call to ?C?ULDIV and returns both the whole part and the remainder.

  • dear My friend
    you are kindly to give me c51 vertion 7.05
    serial number

    Best regards
    javad majd

  • you are kindly to give me c51 vertion 7.05
    serial number...


    Do not post your serial number to anyone on this forum. No one from Keil Software will ever ask you to post your serial number here.

    Jon