ID Number: Q79152
6.00 6.00a 6.00ax | 6.00 6.00a
MS-DOS | OS/2
buglist6.00 buglist6.00a buglist6.00ax fixlist7.00
Summary:
PROBLEM ID: C9112005
SYMPTOMS
In the Microsoft C Compiler versions 6.0, 6.0a, and 6.0ax,
incorrect code is generated to evaluate an expression when the
expression is a sum that meets the following three criteria:
1. One of the addends is a modulus performed on a global variable of
type char (the char could be local if compiling with /Od).
2. The other addend is the same char variable or an expression
involving that char variable.
3. The sum is cast to a char.
CAUSE
The generated code uses an idiv to perform the modulus operation,
and the quotient is used as the addend rather than the remainder.
RESOLUTION
In the following examples, using the quick compile option, /qc,
causes the correct code to be generated. Also, in the case of the
first example, disabling all optimizations with the /Od switch
allows the correct code to be generated.
STATUS
Microsoft has confirmed this to be a problem in C versions 6.0,
6.0a, and 6.0ax. This problem was corrected in C version 7.0.
More Information:
The following code examples meet the above criteria. In the first
example, the addend is the char variable. In the second example, the
addend is an expression involving the char variable.
Sample Code 1
-------------
/* Compile options needed: no quick compile
*
* Compiling with /Od or /qc generates correct code
*/
#include <stdio.h>
int result;
char val = 15;
void main( )
{
result = (char)( val + val%16 );
printf( "Result = %d\n", result );
}
The expected output is:
Result = 30
The actual output is:
Result = 15
The following is the incorrectly generated code:
; (int) val%16
mov cl, 16 ; put 16 into cl
mov al, BYTE PTR _val ; put val into al
cbw ; sign extend al into ah
idiv cl ; divide ax by cl
; quotient in al, remainder in ah
; add (int) val
add al, BYTE PTR _val ; Incorrect! We should be adding
; to the remainder since a mod
; was performed.
cbw ; sign extend al into ah
mov WORD PTR _result, ax ; store the result
Sample Code 2
-------------
/* Compile options needed: no quick compile
*
* Compiling with /qc generates correct code
*/
#include <stdio.h>
int result;
char val = 15;
void main( )
{
result = (char)( (int) val/16 + (int) val%16 );
printf( "Result = %d\n", result );
}
The expected output is:
Result = 15
The actual output is:
Result = 0
The following is the code incorrectly generated for the sum:
; (int) val%16
mov al, BYTE PTR _val ; put val into al
mov cl, 16 ; put 16 into cl
cbw ; sign extend al into ah
idiv cl ; divide ax by cl
; quotient in al, remainder in ah
mov dx, ax ; temporarily store result in dx
; (int) val/16
mov al, BYTE PTR _val ; put val into al
cbw ; sign extend al into ah
idiv cl ; divide ax by cl
; add together and put into result
add al, dl ; Incorrect! Remainder from the
; mod operation is in dh, not dl.
cbw ; sign extend al into ah
mov WORD PTR _result, ax ; store the result
Additional reference words: 6.00 6.00a 6.00ax