ARM Technical Support Knowledge Articles

MULTIPLICATION BUG

Applies to: C166 C Compiler

Answer

QUESTION

The following C166 code generates incorrect results when compiled.

void test (void)
{
   unsigned long words;
   words =  (128 /2) * 1024;  <------- "words"/registers get loaded with 0!
}

What's going on?

ANSWER

It is true that the above code loads words with 0. Here is the code generated by the C166 compiler:

0000 2804          SUB     R0,#04H
0002 E004          MOV     R4,#00H
0004 E005          MOV     R5,#00H ;*****NOTE 00H HERE.  WE WOULD EXPECT 01H
0006 B840          MOV     [R0],R4         ; words
0008 C4500200      MOV     [R0+#02H],R5    ; words+2
000C 0804          ADD     R0,#04H

This is correct operation according to the ANSI specification 6.2.1.5 Usual Arithmetic Conversions. This is because the numeric constants are interpreted as int types (16-bits) in this case. Change at least one of the constants to unsigned longs using the UL suffix. For example,

   volatile unsigned long words;
   words =  (128 /2UL) * 1024;

And, the compiler generates the following code which is more like what you'd expect:

0000 2804          SUB     R0,#04H
0002 E004          MOV     R4,#00H
0004 E015          MOV     R5,#01H ;*****NOTE 01H INSTEAD OF 00H
0006 B840          MOV     [R0],R4         ; words
0008 C4500200      MOV     [R0+#02H],R5    ; words+2
000C 0804          ADD     R0,#04H
000E CB00          RET

Article last edited on: 2004-05-16 17:11:19

Rate this article

[Bad]
|
|
[Good]
Disagree? Move your mouse over the bar and click

Did you find this article helpful? Yes No

How can we improve this article?

Link to this article
Copyright © 2011 ARM Limited. All rights reserved. External (Open), Non-Confidential