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

Parents Reply Children
  • 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.