ID Number: Q33368
5.10 6.00 6.00a 6.00ax 7.00 | 5.10 6.00 6.00a
MS-DOS | OS/2
buglist5.10 buglist6.00 buglist6.00a buglist6.00ax buglist7.00
Summary:
SYMPTOMS
In Microsoft C versions 5.1, 6.0, 6.0a, 6.0ax, and C/C++ version 7.0,
incorrect code may be generated for arithmetic operations on unsigned
chars that are located inside of loops. This problem may occur when
relaxed alias checking (/Oa) is used with loop optimization (/Ol).
RESOLUTION
Turning off either loop optimization or relaxed alias checking may
alleviate the problem. Also, in the example below, casting TestVar
to an unsigned short in the statement that calculates ProcessVar
may alleviate the problem. Declaring the variables in question to
unsigned short will solve the problem.
STATUS
Microsoft has confirmed this to be a problem in C versions 5.1,
6.0, 6.0a, 6.0ax, and C/C++ version 7.0. We are researching this
problem and will post new information here as it becomes available.
More Information:
The following code should print the remainder multiplied by 10 of
each number entered. However, ProcessVar is erroneously always zero.
Sample Code
-----------
/* Compile options needed:
*/
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char *argv[]);
int main (int argc, char *argv[])
{
unsigned char TestVar;
unsigned char ProcessVar;
int i;
if (argc < 2)
printf("usage: %s <integer 1> <integer 2>...<integer n>\n",argv[0]);
else {
for (i = 1; i < argc; i++) {
TestVar = (unsigned char) atoi (argv[i]);
ProcessVar = (unsigned char) ((TestVar % 10) * 10);
printf("ProcessVar: %d\n", ProcessVar);
}
}
return 0;
}
The incorrect assembly for the arithmetic operation is as follows:
;|*** ProcessVar = (TestVar % 10) * 10;
; Line 19
*** 000045 2a e4 sub ah,ah
*** 000047 8b c2 mov ax,dx
*** 000049 d0 e2 shl dl,1
*** 00004b d0 e2 shl dl,1
*** 00004d 02 d0 add dl,al
*** 00004f d0 e2 shl dl,1
*** 000051 88 56 fe mov BYTE PTR [bp-2],dl
Additional reference words: 5.10 6.00 6.00a 6.00ax 7.00