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

Problem with Assignment Operator Modulo

According to K&R:

x *= y + 1

is equivalent to:

x = x * ( y + 1 )

And other assignment operators including modulo should be handled similarly.

However, the following function does not work as I expected.

void test() small
{
    unsigned char	x,y;

    x = 7;
    y = 7;

    x++;
    x %= 256;

    y = ( y + 1 ) % 256;

}

When executed, y is 8 (as expected) but x is set to zero.

An inspection of the assembly listing shows why:

             ; FUNCTION test (BEGIN)
                                           ; SOURCE LINE # 1002
                                           ; SOURCE LINE # 1006
;---- Variable 'x' assigned to Register 'R7' ----
0000 7F07              MOV     R7,#07H
                                           ; SOURCE LINE # 1007
;---- Variable 'y' assigned to Register 'R6' ----
0002 7E07              MOV     R6,#07H
                                           ; SOURCE LINE # 1009
0004 0F                INC     R7
                                           ; SOURCE LINE # 1010
0005 EF                MOV     A,R7
0006 75F000            MOV     B,#00H
0009 84                DIV     AB
000A AFF0              MOV     R7,B
                                           ; SOURCE LINE # 1012
000C EE                MOV     A,R6
000D 04                INC     A
000E FD                MOV     R5,A
000F 0E                INC     R6
                                           ; SOURCE LINE # 1014
0010 22                RET     
             ; FUNCTION test (END)

There is a division by zero, and where did that move to R5 come from.

Is this a compiler bug? It has caused me problems because my application had a modulus that was #define'd - when I changed my buffer length strange things started to happen. I got around the problem by avoiding the assignment operator.

Parents
  • Thanks for the reply.

    I came across the problem in a buffer handling function where I was incrementing read/write pointers that index a circular buffer. In the original application, the modulo values were #define'd as the length of the buffer array - rather than being written as literal. I only hit a problem when I increased the buffer length to the maximum value of 256.

    I can understand where the division by zero comes from, on reflection, it may be a side effect from suppressing interger promotion. However, it does not seem right - especially as the calculation for 'y' comes out as I would expect. I cannot see any reason why 'x' and 'y' should not be equal at the end of test();

    I am still baffled by the assembly language emitted by the compiler - although the compiler generally seems very good it does sometimes seem to loose the plot. The compiler emitted four assembly language instructions for source line 1012 where only one was really necessary.

Reply
  • Thanks for the reply.

    I came across the problem in a buffer handling function where I was incrementing read/write pointers that index a circular buffer. In the original application, the modulo values were #define'd as the length of the buffer array - rather than being written as literal. I only hit a problem when I increased the buffer length to the maximum value of 256.

    I can understand where the division by zero comes from, on reflection, it may be a side effect from suppressing interger promotion. However, it does not seem right - especially as the calculation for 'y' comes out as I would expect. I cannot see any reason why 'x' and 'y' should not be equal at the end of test();

    I am still baffled by the assembly language emitted by the compiler - although the compiler generally seems very good it does sometimes seem to loose the plot. The compiler emitted four assembly language instructions for source line 1012 where only one was really necessary.

Children
No data