Q43912: C: /Oa Causes Changes in Variable Values to Be Ignored

Article: Q43912
Product(s): See article
Version(s): 5.10   | 5.10
Operating System(s): MS-DOS | OS/2
Keyword(s): ENDUSER | SR# G890421-16911 alias buglist5.10 | mspl13_c
Last Modified: 1-JUN-1989

The code generated by the following program is incorrect when
compiled with /Oa (with or without other optimizations). Two workarounds
are to compile without /Oa or to use a temporary variable.

A program that demonstrates the error and an assembly listing of the
code follows:

Source:

static int index;
static int len;
static char *strbuf;

void main()
{
    if (index >= len)
    {
        strbuf[len++] = ' ';      /* works correctly */
        strbuf[len] = '\0';       /* null is put in the wrong place! */
    }
}

Assembly listing:

_main:
7:      {
5C83:0000 56             PUSH      SI
8:          if (index >= len)
5C83:0001 A1DE01         MOV       AX,Word Ptr [len (01DE)]
5C83:0004 3906DA01       CMP       Word Ptr [index (01DA)],AX
5C83:0008 7C13           JL        _main+1d (001D)
10:            strbuf[len++] = ' ';               /* works correctly */
5C83:000A BEDE01         MOV       SI,len (01DE)
5C83:000D 8B1C           MOV       BX,Word Ptr [SI]
5C83:000F FF04           INC       Word Ptr [SI]
5C83:0011 8B36DC01       MOV       SI,Word Ptr [strbuf (01DC)]
5C83:0015 C60020         MOV       Byte Ptr [BX+SI],20
11:            strbuf[len] = '\0';    /* null is put in the wrong place */
5C83:0018 8BD8           MOV       BX,AX
5C83:001A C60000         MOV       Byte Ptr [BX+SI],00
13:     }
5C83:001D 5E             POP       SI

The "MOV BX, AX" generated for "strbuf[len] = '\0';" above should be a
"MOV BX, [len]". AX contains the old value of len at this point, not
the incremented value.