KnowledgeBase Archive

An Archive of Early Microsoft KnowledgeBase Articles

View on GitHub

Q66051: C 6.00 Optimization Pops Too Much Off Stack in Some Situations

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

In certain situations involving the passing of structures to a
function, Microsoft C version 6.00's optimizations can cause too many
bytes to be popped off the stack in preparation for the function call.
In addition, the actual structure can be placed on the stack
incorrectly. Currently, the only workaround is to compile without any
optimizations.

The following code demonstrates the problem. When compiled in Large or
Compact model (/AL or /AC) with even default optimizations enabled,
too many bytes are popped off the stack as is demonstrated by the
extracts from the .COD files reproduced below.

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

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

#include<stdio.h>

#define EDGE 1
typedef struct _point_
   {
      double x;
      double y;
   } _point;

typedef struct _window_
   {
      _point min_scale;
      _point max_scale;
      struct _window_ *data_windows_list;
      struct _window_ *current_data_window;
      struct _window_ *next_window;
   } _window;

typedef struct _display_
   {
      _point min_scale;
      _point max_scale;
      _window *current_window;
      _window *windows_list;
   } _display;

int d_edge_window (_display *display);
int d_edge_window_1(_display *display);
int d_rectangle(_display *display, _point corner_1,
                _point corner_2,int fill);

int d_rectangle(_display *display,_point corner_1,
                       _point corner_2,int fill)
{
  printf("%lf %lf %lf %lf %lf %lf %d \n",
             display->min_scale.x,display->min_scale,
             corner_1.x,corner_1.y,corner_2.x,corner_2.y,fill);
}

void main(void)
{
   _window moo;
   _display goo;

   goo.min_scale.x=1.1;
   goo.min_scale.y=2.2;
   goo.max_scale.x=3.3;
   goo.max_scale.y=4.4;
   goo.current_window=&moo;
   goo.windows_list=&moo;

   moo.data_windows_list=&moo;
   moo.current_data_window=&moo;
   moo.next_window=&moo;
   moo.min_scale.x=5.5;
   moo.min_scale.y=6.6;
   moo.max_scale.x=7.7;
   moo.max_scale.y=8.8;

   d_edge_window(&goo);
   d_edge_window_1(&goo);
}

int d_edge_window(_display *display)
{
   d_rectangle(display,display->current_window->min_scale,
                        display->current_window->max_scale,EDGE);
   return 0;
}

int d_edge_window_1 (_display *display)
{
   d_rectangle(display,display->min_scale,display->max_scale,EDGE);
   return 0;
}

Partial .COD Listing
--------------------

;   display = 6
;|***   d_rectangle(display,display->current_window->min_scale,
;|***               display->current_window->max_scale,EDGE);
; Line 64
    *** 000005  6a 01        push 1         ; push EDGE on stack
    *** 000007  c4 5e 06     les  bx,DWORD PTR [bp+6]    ;display
    *** 00000a  26 8b 47 20  mov  ax,WORD PTR es:[bx+32]
    *** 00000e  26 8b 57 22  mov  dx,WORD PTR es:[bx+34]
    *** 000012  8b c8        mov  cx,ax
    *** 000014  8b f2        mov  si,dx
    *** 000016  05 10 00     add  ax,16
    *** 000019  8b f9        mov  di,cx
    *** 00001b  83 ec 10     sub  sp,16 ; make room for max_scale
    *** 00001e  57           push di
    *** 00001f  56           push si
    *** 000020  1e           push ds
    *** 000021  8b f0        mov  si,ax
    *** 000023  8b fc        mov  di,sp
    *** 000025  83 c7 0c     add  di,12 ; should be add di,6
    *** 000028  16           push ss
    *** 000029  07           pop  es
    *** 00002a  8e da        mov  ds,dx
    ASSUME DS: NOTHING
    *** 00002c  b9 08 00     mov  cx,8
    *** 00002f  f3           rep
    *** 000030  a5           movsw      ; copy max_scale to stack
    *** 000031  1f           pop  ds
    ASSUME DS: DGROUP
    *** 000032  07           pop  es    ; es shouldn't be popped
    *** 000033  5e           pop  si
    *** 000034  5f           pop  di
    *** 000035  83 ec 10     sub  sp,16 ; make room for min_scale
    *** 000038  06           push es    ; rest has been thrown off
    *** 000039  1e           push ds
    *** 00003a  56           push si
    *** 00003b  8b f7        mov  si,di
    *** 00003d  8b fc        mov  di,sp
    *** 00003f  83 c7 08     add  di,8
    *** 000042  16           push ss
    *** 000043  07           pop  es
    *** 000044  1f           pop  ds
    ASSUME DS: DGROUP
    *** 000045  b9 08 00     mov  cx,8
    *** 000048  f3           rep
    *** 000049  a5           movsw
    *** 00004a  1f           pop  ds
    ASSUME DS: DGROUP
    *** 00004b  07           pop  es
    *** 00004c  06           push es
    *** 00004d  53           push bx
    *** 00004e  9a 00 00 00 00  call  FAR PTR _d_rectangle
    *** 000053  83 c4 26     add  sp,38
;|***   return 0;

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.