Microsoft KB Archive/58669

Bad Code Generated for Structure Member Storage PSS ID Number: Q58669 Article last modified on 10-01-1992 PSS database name: S_QuickC

2.00 2.01

MS-DOS

Summary:

In certain cases, Microsoft QuickC versions 2.0 and 2.01 and Microsoft QuickAssembler version 2.01 generate code that incorrectly stores values in structure members.

The conditions required for this to happen are as follows:


 * Optimization has been enabled with -O or -Ox (not -Ol).
 * The member being accessed is offset one or more bytes from the beginning of the structure.
 * The value being stored in the member has been placed in the AX register as the return value of a function.

If these three conditions have been met, the compiler will generate code that overwrites AX before attempting to store its value in the member of the structure.

Sample Code
/* Compile in any memory model. / / Use -O or -Ox optimization switch. */


 * 1) include 

typedef struct teststruct { short padding; /* This padding must be here / short element; / Element will be corrupted */ }TESTSTRUCT;

short UseAX( void ); /* Just to get a usable value void callfunc( TESTSTRUCT * ); /* Demonstrates corruption of AX */

short UseAX { return(1); }

void callfunc( TESTSTRUCT *pTeststruct ) { short Temp;

Temp = UseAX; /* Set up AX with return value / pTeststruct->element = Temp; / Temp is in AX, but AX gets corrupted */

printf( “pTeststruct->element should be: %d”, Temp ); printf( “pTeststruct->element is: %d”, pTeststruct->element ); }

void main { TESTSTRUCT t; callfunc( &t ); }

More Information:

The following code fragment and disassembly demonstrates the problem:

void callfunc( TESTSTRUCT *pTeststruct ) { short Temp;

Temp = UseAX; pTeststruct->element = Temp; /* Second element of the struct */

call _UseAX mov word ptr [Temp], AX ; Store return value in Temp mov ax, word ptr [pTeststruct] ; Address of our structure into AX add ax, 0002 ; Offset past padding mov word ptr [bx], ax ; AX no longer contains Temp

To work around this problem, insert code between the function call and storage statement that makes use of AX. One way to do this is to use an inline assembly instruction. For example:

void callfunc( TESTSTRUCT *pTeststruct ) { short Temp;

Temp = UseAX; _asm { mov ax, 1 } /* This will correct it */ pTeststruct->element = Temp;

printf( “pTeststruct->element should be: %d”, Temp ); printf( “pTeststruct->element is: %d”, pTeststruct->element ); }

This causes the compiler to generate code that no longer relies on the presence of the value of Temp in the AX register.

Microsoft has confirmed this to be a problem in QuickC versions 2.0 and 2.01 and in QuickAssembler version 2.01. We are researching this problem and will post new information here as it becomes available.

Additional reference words: 2.00

Copyright Microsoft Corporation 1992.