Why is the stack frame pointer (EBP) incorrect in assembly release?

I noticed that the EBP pointer on top of the stack frame is not quite right when creating a simple plain MFC application object, and this only happens in a release build. Here is the code.

    // support Restart Manager
    m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_ALL_ASPECTS; 
#ifdef _MANAGED
    // If the application is built using Common Language Runtime support (/clr):
    //     1) This additional setting is needed for Restart Manager support to work properly.
    //     2) In your project, you must add a reference to System.Windows.Forms in order to build.
    // breakpoint here, EBP is correct

    // TODO: replace application ID string below with unique ID string; recommended
    // format for string is CompanyName.ProductName.SubProduct.VersionInformation

    // TODO: add construction code here,
    // Place all significant initialization in InitInstance

// The one and only CMDIDemoApp object

CMDIDemoApp theApp; // breakpoint here, EBP is not what I would expect

// CMDIDemoApp initialization

BOOL CMDIDemoApp::InitInstance()
    // InitCommonControlsEx() is required on Windows XP if an application
    // manifest specifies use of ComCtl32.dll version 6 or later to enable
    // visual styles.  Otherwise, any window creation will fail.
    INITCOMMONCONTROLSEX InitCtrls; // breakpoint here again EBP is good
    InitCtrls.dwSize = sizeof(InitCtrls);
    // Set this to include all the common control classes you want to use
    // in your application.
    InitCtrls.dwICC = ICC_WIN95_CLASSES;


    // Initialize OLE libraries
    if (!AfxOleInit())
        return FALSE;



    // AfxInitRichEdit2() is required to use RichEdit control   
    // AfxInitRichEdit2();

    // Standard initialization
    // If you are not using these features and wish to reduce the size
    // of your final executable, you should remove from the following
    // the specific initialization routines you do not need
    // Change the registry key under which our settings are stored
    // TODO: You should modify this string to be something appropriate
    // such as the name of your company or organization
    SetRegistryKey(_T("Local AppWizard-Generated Applications"));
    LoadStdProfileSettings(4);  // Load standard INI file options (including MRU)

    // Register the application document templates.  Document templates
    //  serve as the connection between documents, frame windows and views
    CMultiDocTemplate* pDocTemplate;
    pDocTemplate = new CMultiDocTemplate(IDR_MDIDemoTYPE,
        RUNTIME_CLASS(CChildFrame), // custom MDI child frame
    if (!pDocTemplate)
        return FALSE;

    // create main MDI Frame window
    CMainFrame* pMainFrame = new CMainFrame;
    if (!pMainFrame || !pMainFrame->LoadFrame(IDR_MAINFRAME))
        delete pMainFrame;
        return FALSE;
    m_pMainWnd = pMainFrame;

    // Parse command line for standard shell commands, DDE, file open
    CCommandLineInfo cmdInfo;

    // Dispatch commands specified on the command line.  Will return FALSE if
    // app was launched with /RegServer, /Register, /Unregserver or /Unregister.
    if (!ProcessShellCommand(cmdInfo))
        return FALSE;
    // The main window has been initialized, so show and update it

    return TRUE;


The stack in WinDbg is at a breakpoint at line CMDIDemoApp theApp;

0:000> k
 # ChildEBP RetAddr  
00 0049fbdc 638381cd MDIDemo!`dynamic initializer for 'theApp'' [e:\projects\vs2015 projects\mdidemo\mdidemo\mdidemo.cpp @ 55]
01 0049fbf8 001826c5 ucrtbase!_initterm+0x6d
02 0049fc3c 765d336a MDIDemo!__scrt_common_main_seh+0x7b [f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl @ 221]
03 0049fc48 76f59902 kernel32!BaseThreadInitThunk+0xe
04 0049fc88 76f598d5 ntdll!__RtlUserThreadStart+0x70
05 0049fca0 00000000 ntdll!_RtlUserThreadStart+0x1b
0:000> dc 0049fbdc 
0049fbdc  00000e00 638381cd 00000000 00000000  .......c........
0049fbec  7efde000 00000005 1c53dd92 0049fc3c  ...~......S.<.I.
0049fbfc  001826c5 00184604 00184618 04b2f942  .&...F...F..B...
0049fc0c  00000000 00000000 7efde000 0049fc00  ...........~..I.
0049fc1c  00000000 00000000 0049fc08 000000fd  ..........I.....
0049fc2c  0049fc78 00182c2a 04e3677e 00000000  x.I.*,..~g......
0049fc3c  0049fc48 765d336a 7efde000 0049fc88  H.I.j3]v...~..I.
0049fc4c  76f59902 7efde000 6fe6f10a 00000000  ...v...~...o....
0:000> dc 0049fbf8 
0049fbf8  0049fc3c 001826c5 00184604 00184618  <.I..&...F...F..
0049fc08  04b2f942 00000000 00000000 7efde000  B..............~
0049fc18  0049fc00 00000000 00000000 0049fc08  ..I...........I.
0049fc28  000000fd 0049fc78 00182c2a 04e3677e  ....x.I.*,..~g..
0049fc38  00000000 0049fc48 765d336a 7efde000  ....H.I.j3]v...~
0049fc48  0049fc88 76f59902 7efde000 6fe6f10a  ..I....v...~...o
0049fc58  00000000 00000000 7efde000 00000000  ...........~....
0049fc68  00000000 00000000 0049fc54 00000000  ........T.I.....
0:000> dc 0049fc3c 
0049fc3c  0049fc48 765d336a 7efde000 0049fc88  H.I.j3]v...~..I.
0049fc4c  76f59902 7efde000 6fe6f10a 00000000  ...v...~...o....
0049fc5c  00000000 7efde000 00000000 00000000  .......~........
0049fc6c  00000000 0049fc54 00000000 ffffffff  ....T.I.........
0049fc7c  76f958c5 195bcba2 00000000 0049fca0  .X.v..[.......I.
0049fc8c  76f598d5 001827b2 7efde000 00000000  ...v.'.....~....
0049fc9c  00000000 00000000 00000000 001827b2  .............'..
0049fcac  7efde000 00000000 00000000 00000000  ...~............


Note what it dc 0049fbdc

should have given 0049fbf8

, but it instead 00000e00

. Why does this happen and only in release? This is really correct in a debug build.

Also EFPs are correct when I set breakpoints in the constructor ( CMDIDemoApp::CMDIDemoApp()

) or any other function like CMDIDemoApp::InitInstance()

. So it is correct in any function, but not entirely correct when declaring a global object.

This is in contrast to my earlier question where EFP is simply wrong even in normal functions like constructor and InitIntance () in this project. The purpose of this question is to provide more information because in this case we know pretty well that the code is not broken, this is the default mfc application without any changes. This also qualifies as a separate issue.


Assembly code in line CMDIDemoApp theApp


0:000> u
MDIDemo!`dynamic initializer for 'theApp'' [e:\projects\vs2015 projects\mdidemo\mdidemo\mdidemo.cpp @ 55]:
00ee1000 55              push    ebp
00ee1001 8bec            mov     ebp,esp
00ee1003 68cc000000      push    0CCh
00ee1008 b9a892ee00      mov     ecx,offset MDIDemo!theApp (00ee92a8)
00ee100d e86e0e0000      call    MDIDemo!CMDIDemoApp::__autoclassinit2 (00ee1e80)
00ee1012 b9a892ee00      mov     ecx,offset MDIDemo!theApp (00ee92a8)
00ee1017 e8a4050000      call    MDIDemo!CMDIDemoApp::CMDIDemoApp (00ee15c0)
00ee101c 680040ee00      push    offset MDIDemo!`dynamic atexit destructor for 'theApp'' (00ee4000)


The constructor node is as follows

00ee15c0 55              push    ebp
00ee15c1 8bec            mov     ebp,esp
00ee15c3 6aff            push    0FFFFFFFFh
00ee15c5 68a83eee00      push    offset MDIDemo!__scrt_stub_for_acrt_initialize+0x4c (00ee3ea8)
00ee15ca 64a100000000    mov     eax,dword ptr fs:[00000000h]
00ee15d0 50              push    eax
00ee15d1 51              push    ecx
00ee15d2 a11490ee00      mov     eax,dword ptr [MDIDemo!__security_cookie (00ee9014)]
00ee15d7 33c5            xor     eax,ebp
00ee15d9 50              push    eax
00ee15da 8d45f4          lea     eax,[ebp-0Ch]
00ee15dd 64a300000000    mov     dword ptr fs:[00000000h],eax
00ee15e3 894df0          mov     dword ptr [ebp-10h],ecx
00ee15e6 6a00            push    0
00ee15e8 8b4df0          mov     ecx,dword ptr [ebp-10h]



source to share

All Articles