编译器链接启动代码crtexe.c

你是否想过为什么有时候main()函数是入口地址,在win32中winmain()函数又是入口地址,其实是编译器在动态链接到crt[C runtime library(part of the C standard library)]时候设置的

程序设置断点,我们来看crtexe.c代码

第一个static int __cdecl pre_c_init(void)

*       The code in mainCRTStartup that was executed before executing C   initializers was shifted in this function. Also this funciton is the   first thing that is executed in c init section.

什么意思不用详细说,老外的注释很给力

static int __cdecl pre_c_init(void)
{
    /*
     * Determine if this is a managed application
     */
    managedapp = check_managed_app();

    /*
     * Set __app_type properly
     */
#ifdef _WINMAIN_    //根据WINMAIN宏来设置应用程序是GUI程序还是控制台程序
    __set_app_type(_GUI_APP);
#else  /* _WINMAIN_ */
    __set_app_type(_CONSOLE_APP);
#endif  /* _WINMAIN_ */

    /*
     * Mark this module as an EXE file so that atexit/_onexit
     * will do the right thing when called, including for C++
     * d-tors.
     */
    __onexitbegin = __onexitend = (_PVFV *)_encode_pointer((_PVFV *)(-1));

    /*
     * Propogate the _fmode and _commode variables to the DLL
     */
    *_IMP___FMODE = _fmode;
    *_IMP___COMMODE = _commode;

#ifdef _M_IX86
    /*
     * Set the local copy of the Pentium FDIV adjustment flag
     */

    _adjust_fdiv = * _imp___adjust_fdiv;
#endif  /* _M_IX86 */

    /*
     * Run the RTC initialization code for this DLL
     */
#ifdef _RTC
    _RTC_Initialize();
#endif  /* _RTC */

    /*
     * Call _setargv(), which will trigger a call to __setargv() if
     * SETARGV.OBJ is linked with the EXE.  If SETARGV.OBJ is not
     * linked with the EXE, a dummy _setargv() will be called.
     */
#ifdef WPRFLAG
    _wsetargv();
#else  /* WPRFLAG */
    _setargv();
#endif  /* WPRFLAG */

    /*
     * If the user has supplied a _matherr routine then set
     * __pusermatherr to point to it.
     */
    if ( !__defaultmatherr )
        __setusermatherr(_matherr);

#ifdef _M_IX86
    _setdefaultprecision();
#endif  /* _M_IX86 */

    /* Enable per-thread locale if user asked for it */
    if(__globallocalestatus == -1)
    {
        _configthreadlocale(-1);
    }

    return 0;
}
这个函数在crt0dat.c中被调用,详细介绍,略去

第二个函数

static void __cdecl pre_cpp_init(void)
static void __cdecl pre_cpp_init(void)
{
#ifdef _RTC
    atexit(_RTC_Terminate);  //注册程序退出时的清理工
#endif  /* _RTC */

    /*
     * Get the arguments for the call to main. Note this must be
     * done explicitly, rather than as part of the dll's
     * initialization, to implement optional expansion of wild
     * card chars in filename args
     */

    startinfo.newmode = _newmode;


#ifdef WPRFLAG
    argret = __wgetmainargs(&argc, &argv, &envp,
                            _dowildcard, &startinfo);
#else  /* WPRFLAG */
    argret = __getmainargs(&argc, &argv, &envp,
                           _dowildcard, &startinfo);
#endif  /* WPRFLAG */

#ifndef _SYSCRT
    if (argret < 0)
        _amsg_exit(_RT_SPACEARG);
#endif  /* _SYSCRT */
}


下面是程序的第一个入口处

static
int
__tmainCRTStartup(
         void
         );

#ifdef _WINMAIN_

#ifdef WPRFLAG
int wWinMainCRTStartup(
#else  /* WPRFLAG */
int WinMainCRTStartup(
#endif  /* WPRFLAG */

#else  /* _WINMAIN_ */

#ifdef WPRFLAG
int wmainCRTStartup(
#else  /* WPRFLAG */
int mainCRTStartup(
#endif  /* WPRFLAG */

#endif  /* _WINMAIN_ */
        void
        )
{
        /*
         * The /GS security cookie must be initialized before any exception
         * handling targetting the current image is registered.  No function
         * using exception handling can be called in the current image until
         * after __security_init_cookie has been called.
         */
        __security_init_cookie();

        return __tmainCRTStartup();
}


/***
*mainCRTStartup(void)
*wmainCRTStartup(void)
*WinMainCRTStartup(void)
*wWinMainCRTStartup(void)
*
*Purpose:
*       These routines do the C runtime initialization, call the appropriate
*       user entry function, and handle termination cleanup.  For a managed
*       app, they then return the exit code back to the calling routine, which
*       is the managed startup code.  For an unmanaged app, they call exit and
*       never return.
*
*       Function:               User entry called:
*       mainCRTStartup          main
*       wmainCRTStartup         wmain
*       WinMainCRTStartup       WinMain
*       wWinMainCRTStartup      wWinMain

就是为程序找到入口地址,具体的判断是在函数 __tmainCRTStartup()中

关键代码:

#ifdef WPRFLAG
            mainret = wWinMain(
#else  /* WPRFLAG */
            mainret = WinMain(
#endif  /* WPRFLAG */
                       (HINSTANCE)&__ImageBase,
                       NULL,
                       lpszCommandLine,
                       StartupInfo.dwFlags & STARTF_USESHOWWINDOW
                        ? StartupInfo.wShowWindow
                        : SW_SHOWDEFAULT
                      );
#else  /* _WINMAIN_ */

#ifdef WPRFLAG
            __winitenv = envp;
            mainret = wmain(argc, argv, envp);
#else  /* WPRFLAG */
            __initenv = envp;
            mainret = main(argc, argv, envp);
#endif  /* WPRFLAG */

#endif  /* _WINMAIN_ */

我们看到,根据宏WPRFLAG来判断是wWinmain()还是WinMain(),根据_WINMAIN_来判断入口函数是main(),wmain()还是WinMain(),wWinMain()

wmain()和wWinMain()是unicode版的,main()和WinMain()是ANSI版的 不过在程序中始终没有找到宏WPRFLAG是在哪里定义的,有空了再详细研究

然后就找到对应的入口程序执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值