KnowledgeBase Archive

An Archive of Early Microsoft KnowledgeBase Articles

View on GitHub

Q62305: _fastcall Register Argument Has Incorrect Value

Article: Q62305
Product(s): See article
Version(s): 6.00   | 6.00
Operating System(s): MS-DOS | OS/2
Keyword(s): ENDUSER | buglist6.00 fastcall | mspl13_c
Last Modified: 15-NOV-1990

In the case below, the Microsoft C 6.00 compiler will generate
incorrect code for enregistering the arguments of a function declared
with the _fastcall attribute.

The following code provides an example of this behavior:

Sample Code
-----------

#include <stddef.h>

void init_windows( void );

void _fastcall wxxopen( short   up_r,
                        short   up_c,
                        short   lo_r,
                        short   lo_c,
                        char    *title,
                        short   ctrl,
                        short   dth,
                        short   wth,
                        short   wc,
                        short   fch );

void init_windows()
{
    wxxopen( 00, 00, 02, 79, NULL, 10, 0, 0, 0, 32 );
    wxxopen( 04, 01, 11, 78, NULL, 10, 0, 0, 0, 32 );
    wxxopen( 22, 00, 24, 79, NULL, 10, 0, 0, 0, 32 );
}

The incorrectly generated code is for the third call to wxxopen().
Rather than 0 (zero) being placed into the DX register for the second
argument, a copy of the AX register, which contains 22, is moved into
DX. This can be clearly seen in the following code lifted from the
.COD file generated for the above source.

Sample Code
-----------

;|***     wxxopen( 22, 00, 24, 79, NULL, 10, 0, 0, 0, 32 );
; Line 22
        *** 000041      b8 4f 00        mov     ax,79
        *** 000044      50              push    ax
        *** 000045      2b c0           sub     ax,ax
        *** 000047      50              push    ax
        *** 000048      b8 0a 00        mov     ax,10
        *** 00004b      50              push    ax
        *** 00004c      2b c0           sub     ax,ax
        *** 00004e      50              push    ax
        *** 00004f      50              push    ax
        *** 000050      50              push    ax
        *** 000051      56              push    si
        *** 000052      b8 16 00        mov     ax,22
        *** 000055      8b d0           mov     dx,ax
        *** 000057      bb 18 00        mov     bx,24
        *** 00005a      e8 00 00        call    @wxxopen

The conditions for the error to occur appear to be very narrowly
defined. The argument being placed into DX must be a constant 0
(zero). The compiler must be in such a state that it considers the AX
register to contain 0 (zero) from a previous operation. This is apparently
the state after the SUB AX, AX instruction above. Regrettably, the AX
register has since been used to hold the first enregistered argument.

It is difficult to convince the compiler to reach this state. The
sequence of three calls to wxxopen() with the specified arguments has
been found to reliably produce the error on the third call.

Microsoft has confirmed this to be a problem with C 6.00. We are
researching this problem and will post new information here as it
becomes available.

THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Copyright Microsoft Corporation 1986-2002.