C 6.00/6.00a May Generate Bad Code for Bit-Wise OR

ID Number: Q71417

6.00 6.00a 6.00ax | 6.00 6.00a

MS-DOS | OS/2

buglist6.00 buglist6.00a buglist6.00ax fixlist7.00

Summary:

In certain situations, the Microsoft C Compiler versions 6.0, 6.0a,

and 6.0ax may not generate the correct code for a bit-wise OR

operation. The sample code below illustrates this problem. The

compiler generates code that incorrectly OR's only the low byte of the

two operands, rather than the full word (16 bits).

To work around this problem, the expression must be broken down into

two simpler expressions. This is shown in the commented code near the

end of the example.

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.

Sample Code

-----------

/* Compile options needed: none

*/

#include <string.h>

unsigned int far *vid_seg=(unsigned int far *) 0xb8000000;

unsigned curs_pos=0xA0;

void display_msg(unsigned char *, unsigned int);

void main(void)

{

unsigned char *tst_msg="TEST MESSAGE";

unsigned tst_attr=0x1700;

display_msg(tst_msg, tst_attr);

}

void display_msg(unsigned char *msg, unsigned int attr)

{

unsigned char ndx;

for ( ndx = 0 ; ndx < strlen(msg) ; ndx++ )

*(vid_seg + curs_pos++)=(*(msg + ndx) & ~0x80) | attr;

/* The line above is where the problem occurs. The following

is a partial listing of the erroneously generated code:

*** 000028 8b d9 mov bx,cx

*** 00002a 8b 76 04 mov si,WORD PTR [bp+4] ;msg

*** 00002d 8a 00 mov al,BYTE PTR [bx][si]

*** 00002f 25 7f 00 and ax,127

*** 000032 0a 46 06 or al,BYTE PTR [bp+6] ;attr

...

To work around the problem, declare a temporary variable and

replace the expression above with the following two lines:

temp=(*(msg + ndx) & ~0x80);

*(vid_seg + curs_pos++)=temp | attr;

*/

}