crt0.c代码内容解释和编译器构造
 /***
/***2
 *crt0.c - C runtime initialization routine
*crt0.c - C runtime initialization routine3
 *
*4
 *       Copyright (c) 1989-1997, Microsoft Corporation. All rights reserved.
*       Copyright (c) 1989-1997, Microsoft Corporation. All rights reserved.5
 *
*6
 *Purpose:
*Purpose:7
 *       This the actual startup routine for apps.  It calls the user's main
*       This the actual startup routine for apps.  It calls the user's main8
 *       routine [w]main() or [w]WinMain after performing C Run-Time Library
*       routine [w]main() or [w]WinMain after performing C Run-Time Library9
 *       initialization.
*       initialization.10
 *
*11
 *       (With ifdef's, this source file also provides the source code for
*       (With ifdef's, this source file also provides the source code for12
 *       wcrt0.c, the startup routine for console apps with wide characters,
*       wcrt0.c, the startup routine for console apps with wide characters,13
 *       wincrt0.c, the startup routine for Windows apps, and wwincrt0.c,
*       wincrt0.c, the startup routine for Windows apps, and wwincrt0.c,14
 *       the startup routine for Windows apps with wide characters.)
*       the startup routine for Windows apps with wide characters.)15
 *
*16
 *******************************************************************************/
*******************************************************************************/17

18
 #ifdef _WIN32
#ifdef _WIN3219

20
 #ifndef CRTDLL
#ifndef CRTDLL21

22
 #include <cruntime.h>
#include <cruntime.h>23
 #include <dos.h>
#include <dos.h>24
 #include <internal.h>
#include <internal.h>25
 #include <stdlib.h>
#include <stdlib.h>26
 #include <string.h>
#include <string.h>27
 #include <rterr.h>
#include <rterr.h>28
 #include <windows.h>
#include <windows.h>29
 #include <awint.h>
#include <awint.h>30
 #include <tchar.h>
#include <tchar.h>31
 #include <dbgint.h>
#include <dbgint.h>32

33
 /*
/*34
 * wWinMain is not yet defined in winbase.h. When it is, this should be
 * wWinMain is not yet defined in winbase.h. When it is, this should be35
 * removed.
 * removed.36
 */
 */37

38
 int
int39
 WINAPI
WINAPI40
 wWinMain(
wWinMain(41
 HINSTANCE hInstance,
    HINSTANCE hInstance,42
 HINSTANCE hPrevInstance,
    HINSTANCE hPrevInstance,43
 LPWSTR lpCmdLine,
    LPWSTR lpCmdLine,44
 int nShowCmd
    int nShowCmd45
 );
    );46

47
 #ifdef WPRFLAG
#ifdef WPRFLAG48
 _TUCHAR * __cdecl _wwincmdln(void);
_TUCHAR * __cdecl _wwincmdln(void);49
 #else  /* WPRFLAG */
#else  /* WPRFLAG */50
 _TUCHAR * __cdecl _wincmdln(void);
_TUCHAR * __cdecl _wincmdln(void);51
 #endif  /* WPRFLAG */
#endif  /* WPRFLAG */52

53
 /*
/*54
 * command line, environment, and a few other globals
 * command line, environment, and a few other globals55
 */
 */56

57
 #ifdef WPRFLAG
#ifdef WPRFLAG58
 wchar_t *_wcmdln;           /* points to wide command line */
wchar_t *_wcmdln;           /* points to wide command line */59
 #else  /* WPRFLAG */
#else  /* WPRFLAG */60
 char *_acmdln;              /* points to command line */
char *_acmdln;              /* points to command line */61
 #endif  /* WPRFLAG */
#endif  /* WPRFLAG */62

63
 char *_aenvptr = NULL;      /* points to environment block */
char *_aenvptr = NULL;      /* points to environment block */64
 wchar_t *_wenvptr = NULL;   /* points to wide environment block */
wchar_t *_wenvptr = NULL;   /* points to wide environment block */65

66

67
 void (__cdecl * _aexit_rtn)(int) = _exit;   /* RT message return procedure */
void (__cdecl * _aexit_rtn)(int) = _exit;   /* RT message return procedure */68

69
 static void __cdecl fast_error_exit(int);   /* Error exit via ExitProcess */
static void __cdecl fast_error_exit(int);   /* Error exit via ExitProcess */70

71
 /*
/*72
 * _error_mode and _apptype, together, determine how error messages are
 * _error_mode and _apptype, together, determine how error messages are73
 * written out.
 * written out.74
 */
 */75
 int __error_mode = _OUT_TO_DEFAULT;
int __error_mode = _OUT_TO_DEFAULT;76
 #ifdef _WINMAIN_
#ifdef _WINMAIN_77
 int __app_type = _GUI_APP;
int __app_type = _GUI_APP;78
 #else  /* _WINMAIN_ */
#else  /* _WINMAIN_ */79
 int __app_type = _CONSOLE_APP;
int __app_type = _CONSOLE_APP;80
 #endif  /* _WINMAIN_ */
#endif  /* _WINMAIN_ */81

82

83
 /***
/***84
 *BaseProcessStartup(PVOID Peb)
*BaseProcessStartup(PVOID Peb)85
 *
*86
 *Purpose:
*Purpose:87
 *       This routine does the C runtime initialization, calls main(), and
*       This routine does the C runtime initialization, calls main(), and88
 *       then exits.  It never returns.
*       then exits.  It never returns.89
 *
*90
 *Entry:
*Entry:91
 *       PVOID Peb - pointer to Win32 Process Environment Block (not used)
*       PVOID Peb - pointer to Win32 Process Environment Block (not used)92
 *
*93
 *Exit:
*Exit:94
 *       This function never returns.
*       This function never returns.95
 *
*96
 *******************************************************************************/
*******************************************************************************/97

98
 #ifdef _WINMAIN_
#ifdef _WINMAIN_99

100
 #ifdef WPRFLAG
#ifdef WPRFLAG101
 void wWinMainCRTStartup(
void wWinMainCRTStartup(102
 #else  /* WPRFLAG */
#else  /* WPRFLAG */103
 void WinMainCRTStartup(
void WinMainCRTStartup(104
 #endif  /* WPRFLAG */
#endif  /* WPRFLAG */105

106
 #else  /* _WINMAIN_ */
#else  /* _WINMAIN_ */107

108
 #ifdef WPRFLAG
#ifdef WPRFLAG109
 void wmainCRTStartup(
void wmainCRTStartup(110
 #else  /* WPRFLAG */
#else  /* WPRFLAG */111
 void mainCRTStartup(
void mainCRTStartup(112
 #endif  /* WPRFLAG */
#endif  /* WPRFLAG */113

114
 #endif  /* _WINMAIN_ */
#endif  /* _WINMAIN_ */115
 void
        void116
 )
        )117

118
 {
{119
 int mainret;
        int mainret;120

121
 #ifdef _WINMAIN_
#ifdef _WINMAIN_122
 _TUCHAR *lpszCommandLine;
        _TUCHAR *lpszCommandLine;123
 STARTUPINFO StartupInfo;
        STARTUPINFO StartupInfo;124
 #endif  /* _WINMAIN_ */
#endif  /* _WINMAIN_ */125

126
 /*
        /*127
 * Get the full Win32 version
         * Get the full Win32 version128
 */
         */129
 _osver = GetVersion();
        _osver = GetVersion();130

131
 _winminor = (_osver >> 8) & 0x00FF ;
        _winminor = (_osver >> 8) & 0x00FF ;132
 _winmajor = _osver & 0x00FF ;
        _winmajor = _osver & 0x00FF ;133
 _winver = (_winmajor << 8) + _winminor;
        _winver = (_winmajor << 8) + _winminor;134
 _osver = (_osver >> 16) & 0x00FFFF ;
        _osver = (_osver >> 16) & 0x00FFFF ;135

136
 #ifdef _MT
#ifdef _MT137
 if ( !_heap_init(1) )               /* initialize heap */
        if ( !_heap_init(1) )               /* initialize heap */138
 #else  /* _MT */
#else  /* _MT */139
 if ( !_heap_init(0) )               /* initialize heap */
        if ( !_heap_init(0) )               /* initialize heap */140
 #endif  /* _MT */
#endif  /* _MT */141
 fast_error_exit(_RT_HEAPINIT);  /* write message and die */
            fast_error_exit(_RT_HEAPINIT);  /* write message and die */142

143
 #ifdef _MT
#ifdef _MT144
 if( !_mtinit() )                    /* initialize multi-thread */
        if( !_mtinit() )                    /* initialize multi-thread */145
 fast_error_exit(_RT_THREAD);    /* write message and die */
            fast_error_exit(_RT_THREAD);    /* write message and die */146
 #endif  /* _MT */
#endif  /* _MT */147

148
 /*
        /*149
 * Guard the remainder of the initialization code and the call
         * Guard the remainder of the initialization code and the call150
 * to user's main, or WinMain, function in a __try/__except
         * to user's main, or WinMain, function in a __try/__except151
 * statement.
         * statement.152
 */
         */153

154
 __try {
        __try {155

156
 _ioinit();                      /* initialize lowio */
            _ioinit();                      /* initialize lowio */157

158
 #ifdef WPRFLAG
#ifdef WPRFLAG159
 /* get wide cmd line info */
            /* get wide cmd line info */160
 _wcmdln = (wchar_t *)__crtGetCommandLineW();
            _wcmdln = (wchar_t *)__crtGetCommandLineW();161

162
 /* get wide environ info */
            /* get wide environ info */163
 _wenvptr = (wchar_t *)__crtGetEnvironmentStringsW();
            _wenvptr = (wchar_t *)__crtGetEnvironmentStringsW();164

165
 _wsetargv();
            _wsetargv();166
 _wsetenvp();
            _wsetenvp();167
 #else  /* WPRFLAG */
#else  /* WPRFLAG */168
 /* get cmd line info */
            /* get cmd line info */169
 _acmdln = (char *)GetCommandLineA();
            _acmdln = (char *)GetCommandLineA();170

171
 /* get environ info */
            /* get environ info */172
 _aenvptr = (char *)__crtGetEnvironmentStringsA();
            _aenvptr = (char *)__crtGetEnvironmentStringsA();173

174
 _setargv();
            _setargv();175
 _setenvp();
            _setenvp();176
 #endif  /* WPRFLAG */
#endif  /* WPRFLAG */177

178
 _cinit();                       /* do C data initialize */
            _cinit();                       /* do C data initialize */179

180
 #ifdef _WINMAIN_
#ifdef _WINMAIN_181

182
 StartupInfo.dwFlags = 0;
            StartupInfo.dwFlags = 0;183
 GetStartupInfo( &StartupInfo );
            GetStartupInfo( &StartupInfo );184

185
 #ifdef WPRFLAG
#ifdef WPRFLAG186
 lpszCommandLine = _wwincmdln();
            lpszCommandLine = _wwincmdln();187
 mainret = wWinMain(
            mainret = wWinMain(188
 #else  /* WPRFLAG */
#else  /* WPRFLAG */189
 lpszCommandLine = _wincmdln();
            lpszCommandLine = _wincmdln();190
 mainret = WinMain(
            mainret = WinMain(191
 #endif  /* WPRFLAG */
#endif  /* WPRFLAG */192
 GetModuleHandleA(NULL),
                               GetModuleHandleA(NULL),193
 NULL,
                               NULL,194
 lpszCommandLine,
                               lpszCommandLine,195
 StartupInfo.dwFlags & STARTF_USESHOWWINDOW
                               StartupInfo.dwFlags & STARTF_USESHOWWINDOW196
 ? StartupInfo.wShowWindow
                                    ? StartupInfo.wShowWindow197
 : SW_SHOWDEFAULT
                                    : SW_SHOWDEFAULT198
 );
                             );199
 #else  /* _WINMAIN_ */
#else  /* _WINMAIN_ */200

201
 #ifdef WPRFLAG
#ifdef WPRFLAG202
 __winitenv = _wenviron;
            __winitenv = _wenviron;203
 mainret = wmain(__argc, __wargv, _wenviron);
            mainret = wmain(__argc, __wargv, _wenviron);204
 #else  /* WPRFLAG */
#else  /* WPRFLAG */205
 __initenv = _environ;
            __initenv = _environ;206
 mainret = main(__argc, __argv, _environ);
            mainret = main(__argc, __argv, _environ);207
 #endif  /* WPRFLAG */
#endif  /* WPRFLAG */208

209
 #endif  /* _WINMAIN_ */
#endif  /* _WINMAIN_ */210
 exit(mainret);
            exit(mainret);211
 }
        }212
 __except ( _XcptFilter(GetExceptionCode(), GetExceptionInformation()) )
        __except ( _XcptFilter(GetExceptionCode(), GetExceptionInformation()) )213
 {
        {214
 /*
            /*215
 * Should never reach here
             * Should never reach here216
 */
             */217
 _exit( GetExceptionCode() );
            _exit( GetExceptionCode() );218

219
 } /* end of try - except */
        } /* end of try - except */220

221
 }
}222

223

224

225
 /***
/***226
 *_amsg_exit(rterrnum) - Fast exit fatal errors
*_amsg_exit(rterrnum) - Fast exit fatal errors227
 *
*228
 *Purpose:
*Purpose:229
 *       Exit the program with error code of 255 and appropriate error
*       Exit the program with error code of 255 and appropriate error230
 *       message.
*       message.231
 *
*232
 *Entry:
*Entry:233
 *       int rterrnum - error message number (amsg_exit only).
*       int rterrnum - error message number (amsg_exit only).234
 *
*235
 *Exit:
*Exit:236
 *       Calls exit() (for integer divide-by-0) or _exit() indirectly
*       Calls exit() (for integer divide-by-0) or _exit() indirectly237
 *       through _aexit_rtn [amsg_exit].
*       through _aexit_rtn [amsg_exit].238
 *       For multi-thread: calls _exit() function
*       For multi-thread: calls _exit() function239
 *
*240
 *Exceptions:
*Exceptions:241
 *
*242
 *******************************************************************************/
*******************************************************************************/243

244
 void __cdecl _amsg_exit (
void __cdecl _amsg_exit (245
 int rterrnum
        int rterrnum246
 )
        )247
 {
{248
 #ifdef _WINMAIN_
#ifdef _WINMAIN_249
 if ( __error_mode == _OUT_TO_STDERR )
        if ( __error_mode == _OUT_TO_STDERR )250
 #else  /* _WINMAIN_ */
#else  /* _WINMAIN_ */251
 if ( __error_mode != _OUT_TO_MSGBOX )
        if ( __error_mode != _OUT_TO_MSGBOX )252
 #endif  /* _WINMAIN_ */
#endif  /* _WINMAIN_ */253
 _FF_MSGBANNER();    /* write run-time error banner */
            _FF_MSGBANNER();    /* write run-time error banner */254

255
 _NMSG_WRITE(rterrnum);  /* write message */
        _NMSG_WRITE(rterrnum);  /* write message */256
 _aexit_rtn(255);        /* normally _exit(255) */
        _aexit_rtn(255);        /* normally _exit(255) */257
 }
}258

259
 /***
/***260
 *fast_error_exit(rterrnum) - Faster exit fatal errors
*fast_error_exit(rterrnum) - Faster exit fatal errors261
 *
*262
 *Purpose:
*Purpose:263
 *       Exit the process with error code of 255 and appropriate error
*       Exit the process with error code of 255 and appropriate error264
 *       message.
*       message.265
 *
*266
 *Entry:
*Entry:267
 *       int rterrnum - error message number (amsg_exit only).
*       int rterrnum - error message number (amsg_exit only).268
 *
*269
 *Exit:
*Exit:270
 *       Calls ExitProcess.
*       Calls ExitProcess.271
 *
*272
 *Exceptions:
*Exceptions:273
 *
*274
 *******************************************************************************/
*******************************************************************************/275

276
 static void __cdecl fast_error_exit (
static void __cdecl fast_error_exit (277
 int rterrnum
        int rterrnum278
 )
        )279
 {
{280
 #ifdef _WINMAIN_
#ifdef _WINMAIN_281
 if ( __error_mode == _OUT_TO_STDERR )
        if ( __error_mode == _OUT_TO_STDERR )282
 #else  /* _WINMAIN_ */
#else  /* _WINMAIN_ */283
 if ( __error_mode != _OUT_TO_MSGBOX )
        if ( __error_mode != _OUT_TO_MSGBOX )284
 #endif  /* _WINMAIN_ */
#endif  /* _WINMAIN_ */285
 _FF_MSGBANNER();    /* write run-time error banner */
            _FF_MSGBANNER();    /* write run-time error banner */286

287
 _NMSG_WRITE(rterrnum);  /* write message */
        _NMSG_WRITE(rterrnum);  /* write message */288
 ExitProcess(255);       /* normally _exit(255) */
        ExitProcess(255);       /* normally _exit(255) */289
 }
}290

291
 #ifndef WPRFLAG
#ifndef WPRFLAG292

293

294
 #endif  /* WPRFLAG */
#endif  /* WPRFLAG */295

296
 #endif  /* CRTDLL */
#endif  /* CRTDLL */297

298
 #else  /* _WIN32 */
#else  /* _WIN32 */299

300
 #include <cruntime.h>
#include <cruntime.h>301
 #include <internal.h>
#include <internal.h>302
 #include <stdlib.h>
#include <stdlib.h>303
 #include <msdos.h>
#include <msdos.h>304
 #include <string.h>
#include <string.h>305
 #include <setjmp.h>
#include <setjmp.h>306
 #include <dbgint.h>
#include <dbgint.h>307
 #include <macos\types.h>
#include <macos\types.h>308
 #include <macos\segload.h>
#include <macos\segload.h>309
 #include <macos\gestalte.h>
#include <macos\gestalte.h>310
 #include <macos\osutils.h>
#include <macos\osutils.h>311
 #include <macos\traps.h>
#include <macos\traps.h>312
 #include <mpw.h>
#include <mpw.h>313

314
 static void __cdecl Inherit(void);  /* local function */
static void __cdecl Inherit(void);  /* local function */315

316
 int __cdecl main(int, char **, char **);             /*generated by compiler*/
int __cdecl main(int, char **, char **);             /*generated by compiler*/317

318
 unsigned long _GetShellStack(void);
unsigned long _GetShellStack(void);319

320
 static char * __cdecl _p2cstr_internal ( unsigned char * str );
static char * __cdecl _p2cstr_internal ( unsigned char * str );321

322
 extern MPWBLOCK * _pMPWBlock;
extern MPWBLOCK * _pMPWBlock;323
 extern int __argc;
extern int __argc;324
 extern char **__argv;
extern char **__argv;325

326
 /***
/***327
 *__crt0()
*__crt0()328
 *
*329
 *Purpose:
*Purpose:330
 *       This routine does the C runtime initialization, calls main(), and
*       This routine does the C runtime initialization, calls main(), and331
 *       then exits.  It never returns.
*       then exits.  It never returns.332
 *
*333
 *Entry:
*Entry:334
 *
*335
 *Exit:
*Exit:336
 *       This function never returns.
*       This function never returns.337
 *
*338
 *******************************************************************************/
*******************************************************************************/339

340
 void __cdecl __crt0 (
void __cdecl __crt0 (341
 )
        )342
 {
{343
 int mainret;
        int mainret;344
 char szPgmName[32];
        char szPgmName[32];345
 char *pArg;
        char *pArg;346
 char *argv[2];
        char *argv[2];347

348
 #ifndef _M_MPPC
#ifndef _M_MPPC349
 void *pv;
        void *pv;350

351
 /* This is the magic stuff that MPW tools do to get info from MPW*/
        /* This is the magic stuff that MPW tools do to get info from MPW*/352

353
 pv = (void *)*(int *)0x316;
        pv = (void *)*(int *)0x316;354
 if (pv != NULL && !((int)pv & 1) && *(int *)pv == 'MPGM') {
        if (pv != NULL && !((int)pv & 1) && *(int *)pv == 'MPGM') {355
 pv = (void *)*++(int *)pv;
            pv = (void *)*++(int *)pv;356
 if (pv != NULL && *(short *)pv == 'SH') {
            if (pv != NULL && *(short *)pv == 'SH') {357
 _pMPWBlock = (MPWBLOCK *)pv;
                _pMPWBlock = (MPWBLOCK *)pv;358
 }
            }359
 }
        }360

361
 #endif  /* _M_MPPC */
#endif  /* _M_MPPC */362

363
 _environ = NULL;
        _environ = NULL;364
 if (_pMPWBlock == NULL) {
        if (_pMPWBlock == NULL) {365
 __argc = 1;
            __argc = 1;366
 memcpy(szPgmName, (char *)0x910, sizeof(szPgmName));
            memcpy(szPgmName, (char *)0x910, sizeof(szPgmName));367
 pArg = _p2cstr_internal(szPgmName);
            pArg = _p2cstr_internal(szPgmName);368
 argv[0] = pArg;
            argv[0] = pArg;369
 argv[1] = NULL;
            argv[1] = NULL;370
 __argv = argv;
            __argv = argv;371

372
 #ifndef _M_MPPC
#ifndef _M_MPPC373
 _shellStack = 0;                        /* force ExitToShell */
            _shellStack = 0;                        /* force ExitToShell */374
 #endif  /* _M_MPPC */
#endif  /* _M_MPPC */375
 }
        }376
 #ifndef _M_MPPC
#ifndef _M_MPPC377
 else {
        else {378
 _shellStack = _GetShellStack();        //return current a6, or first a6
            _shellStack = _GetShellStack();        //return current a6, or first a6379
 _shellStack += 4;                      //a6 + 4 is the stack pointer we want
            _shellStack += 4;                      //a6 + 4 is the stack pointer we want380
 __argc = _pMPWBlock->argc;
            __argc = _pMPWBlock->argc;381
 __argv = _pMPWBlock->argv;
            __argv = _pMPWBlock->argv;382

383
 Inherit();       /* Inherit file handles - env is set up by _envinit if needed */
            Inherit();       /* Inherit file handles - env is set up by _envinit if needed */384
 }
        }385
 #endif  /* _M_MPPC */
#endif  /* _M_MPPC */386

387
 /*
        /*388
 * call run time initializer
         * call run time initializer389
 */
         */390
 __cinit();
        __cinit();391

392
 mainret = main(__argc, __argv, _environ);
        mainret = main(__argc, __argv, _environ);393
 exit(mainret);
        exit(mainret);394
 }
}395

396

397
 #ifndef _M_MPPC
#ifndef _M_MPPC398
 /***
/***399
 *Inherit() - obtain and process info on inherited file handles.
*Inherit() - obtain and process info on inherited file handles.400
 *
*401
 *Purpose:
*Purpose:402
 *
*403
 *       Locates and interprets MPW std files.  For files we just save the
*       Locates and interprets MPW std files.  For files we just save the404
 *       file handles.   For the console we save the device table address so
*       file handles.   For the console we save the device table address so405
 *       we can do console I/O.  In the latter case, FDEV is set in the _osfile
*       we can do console I/O.  In the latter case, FDEV is set in the _osfile406
 *       array.
*       array.407
 *
*408
 *Entry:
*Entry:409
 *       Address of MPW param table
*       Address of MPW param table410
 *
*411
 *Exit:
*Exit:412
 *       No return value.
*       No return value.413
 *
*414
 *Exceptions:
*Exceptions:415
 *
*416
 *******************************************************************************/
*******************************************************************************/417

418
 static void __cdecl Inherit (
static void __cdecl Inherit (419
 void
        void420
 )
        )421
 {
{422
 MPWFILE *pFile;
        MPWFILE *pFile;423
 int i;
        int i;424
 pFile = _pMPWBlock->pFile;
        pFile = _pMPWBlock->pFile;425
 if (pFile == NULL) {
        if (pFile == NULL) {426
 return;
            return;427
 }
        }428
 for (i = 0; i < 3; i++) {
        for (i = 0; i < 3; i++) {429
 switch ((pFile->pDevice)->name) {
            switch ((pFile->pDevice)->name) {430
 case 'ECON':
                case 'ECON':431
 _osfile[i] |= FDEV | FOPEN;
                    _osfile[i] |= FDEV | FOPEN;432
 _osfhnd[i] = (int)pFile;
                    _osfhnd[i] = (int)pFile;433
 break;
                    break;434

435
 case 'FSYS':
                case 'FSYS':436
 _osfile[i] |= FOPEN;
                    _osfile[i] |= FOPEN;437
 _osfhnd[i] = (*(pFile->ppFInfo))->ioRefNum;
                    _osfhnd[i] = (*(pFile->ppFInfo))->ioRefNum;438
 break;
                    break;439
 }
            }440
 pFile++;
            pFile++;441
 }
        }442
 }
}443

444
 #endif  /* _M_MPPC */
#endif  /* _M_MPPC */445

446

447

448
 static char * __cdecl _p2cstr_internal (
static char * __cdecl _p2cstr_internal (449
 unsigned char * str
        unsigned char * str450
 )
        )451
 {
{452
 unsigned char *pchSrc;
        unsigned char *pchSrc;453
 unsigned char *pchDst;
        unsigned char *pchDst;454
 int  cch;
        int  cch;455

456
 if ( str && *str ) {
        if ( str && *str ) {457
 pchDst = str;
            pchDst = str;458
 pchSrc = str + 1;
            pchSrc = str + 1;459

460
 for ( cch=*pchDst; cch; --cch ) {
            for ( cch=*pchDst; cch; --cch ) {461
 *pchDst++ = *pchSrc++;
                *pchDst++ = *pchSrc++;462
 }
            }463

464
 *pchDst = '\0';
            *pchDst = '\0';465
 }
        }466

467
 return( str );
        return( str );468
 }
}469

470
 #endif  /* _WIN32 */
#endif  /* _WIN32 */471

1. 应用程序类型--------只有2类:要么是CUI, 要么是GUI
2. 程序真正的启动代码(入口点函数)-----------各种**CRTStartUp
3. 环境变量+命令行信息的相关变量和函数都在此文件中有定义或声明
4. 调用运行时初始化+main()函数的最后返回和报错信息在下面的代码定义了
 *******************************************************************************/
*******************************************************************************/2

3
 void __cdecl __crt0 (
void __cdecl __crt0 (4
 )
        )5
 {
{6
 int mainret;
        int mainret;7
 char szPgmName[32];
        char szPgmName[32];8
 char *pArg;
        char *pArg;9
 char *argv[2];
        char *argv[2];10

11
 #ifndef _M_MPPC
#ifndef _M_MPPC12
 void *pv;
        void *pv;13

14
 /* This is the magic stuff that MPW tools do to get info from MPW*/
        /* This is the magic stuff that MPW tools do to get info from MPW*/15

16
 pv = (void *)*(int *)0x316;
        pv = (void *)*(int *)0x316;17
 if (pv != NULL && !((int)pv & 1) && *(int *)pv == 'MPGM') {
        if (pv != NULL && !((int)pv & 1) && *(int *)pv == 'MPGM') {18
 pv = (void *)*++(int *)pv;
            pv = (void *)*++(int *)pv;19
 if (pv != NULL && *(short *)pv == 'SH') {
            if (pv != NULL && *(short *)pv == 'SH') {20
 _pMPWBlock = (MPWBLOCK *)pv;
                _pMPWBlock = (MPWBLOCK *)pv;21
 }
            }22
 }
        }23

24
 #endif  /* _M_MPPC */
#endif  /* _M_MPPC */25

26
 _environ = NULL;
        _environ = NULL;27
 if (_pMPWBlock == NULL) {
        if (_pMPWBlock == NULL) {28
 __argc = 1;
            __argc = 1;29
 memcpy(szPgmName, (char *)0x910, sizeof(szPgmName));
            memcpy(szPgmName, (char *)0x910, sizeof(szPgmName));30
 pArg = _p2cstr_internal(szPgmName);
            pArg = _p2cstr_internal(szPgmName);31
 argv[0] = pArg;
            argv[0] = pArg;32
 argv[1] = NULL;
            argv[1] = NULL;33
 __argv = argv;
            __argv = argv;34

35
 #ifndef _M_MPPC
#ifndef _M_MPPC36
 _shellStack = 0;                        /* force ExitToShell */
            _shellStack = 0;                        /* force ExitToShell */37
 #endif  /* _M_MPPC */
#endif  /* _M_MPPC */38
 }
        }39
 #ifndef _M_MPPC
#ifndef _M_MPPC40
 else {
        else {41
 _shellStack = _GetShellStack();        //return current a6, or first a6
            _shellStack = _GetShellStack();        //return current a6, or first a642
 _shellStack += 4;                      //a6 + 4 is the stack pointer we want
            _shellStack += 4;                      //a6 + 4 is the stack pointer we want43
 __argc = _pMPWBlock->argc;
            __argc = _pMPWBlock->argc;44
 __argv = _pMPWBlock->argv;
            __argv = _pMPWBlock->argv;45

46
 Inherit();       /* Inherit file handles - env is set up by _envinit if needed */
            Inherit();       /* Inherit file handles - env is set up by _envinit if needed */47
 }
        }48
 #endif  /* _M_MPPC */
#endif  /* _M_MPPC */49

50
 /*
        /*51
 * call run time initializer
         * call run time initializer52
 */
         */53
 __cinit();
        __cinit();54

55
 mainret = main(__argc, __argv, _environ);
        mainret = main(__argc, __argv, _environ);56
 exit(mainret);
        exit(mainret);57
 }
}58

59

5. 获取进程信息+响应中断的代码如下:
 /***
/***2
 *Inherit() - obtain and process info on inherited file handles.
*Inherit() - obtain and process info on inherited file handles.3
 *
*4
 *Purpose:
*Purpose:5
 *
*6
 *       Locates and interprets MPW std files.  For files we just save the
*       Locates and interprets MPW std files.  For files we just save the7
 *       file handles.   For the console we save the device table address so
*       file handles.   For the console we save the device table address so8
 *       we can do console I/O.  In the latter case, FDEV is set in the _osfile
*       we can do console I/O.  In the latter case, FDEV is set in the _osfile9
 *       array.
*       array.10
 *
*11
 *Entry:
*Entry:12
 *       Address of MPW param table
*       Address of MPW param table13
 *
*14
 *Exit:
*Exit:15
 *       No return value.
*       No return value.16
 *
*17
 *Exceptions:
*Exceptions:18
 *
*19
 *******************************************************************************/
*******************************************************************************/20

21
 static void __cdecl Inherit (
static void __cdecl Inherit (22
 void
        void23
 )
        )24
 {
{25
 MPWFILE *pFile;
        MPWFILE *pFile;26
 int i;
        int i;27
 pFile = _pMPWBlock->pFile;
        pFile = _pMPWBlock->pFile;28
 if (pFile == NULL) {
        if (pFile == NULL) {29
 return;
            return;30
 }
        }31
 for (i = 0; i < 3; i++) {
        for (i = 0; i < 3; i++) {32
 switch ((pFile->pDevice)->name) {
            switch ((pFile->pDevice)->name) {33
 case 'ECON':
                case 'ECON':34
 _osfile[i] |= FDEV | FOPEN;
                    _osfile[i] |= FDEV | FOPEN;35
 _osfhnd[i] = (int)pFile;
                    _osfhnd[i] = (int)pFile;36
 break;
                    break;37

38
 case 'FSYS':
                case 'FSYS':39
 _osfile[i] |= FOPEN;
                    _osfile[i] |= FOPEN;40
 _osfhnd[i] = (*(pFile->ppFInfo))->ioRefNum;
                    _osfhnd[i] = (*(pFile->ppFInfo))->ioRefNum;41
 break;
                    break;42
 }
            }43
 pFile++;
            pFile++;44
 }
        }45
 }
}46

47
 #endif  /* _M_MPPC */
#endif  /* _M_MPPC */48

49

50

51
 static char * __cdecl _p2cstr_internal (
static char * __cdecl _p2cstr_internal (52
 unsigned char * str
        unsigned char * str53
 )
        )54
 {
{55
 unsigned char *pchSrc;
        unsigned char *pchSrc;56
 unsigned char *pchDst;
        unsigned char *pchDst;57
 int  cch;
        int  cch;58

59
 if ( str && *str ) {
        if ( str && *str ) {60
 pchDst = str;
            pchDst = str;61
 pchSrc = str + 1;
            pchSrc = str + 1;62

63
 for ( cch=*pchDst; cch; --cch ) {
            for ( cch=*pchDst; cch; --cch ) {64
 *pchDst++ = *pchSrc++;
                *pchDst++ = *pchSrc++;65
 }
            }66

67
 *pchDst = '\0';
            *pchDst = '\0';68
 }
        }69

70
 return( str );
        return( str );71
 }
}72

73
 #endif  /* _WIN32 */
#endif  /* _WIN32 */6. 如果是GUI程序,则要创建“内核对象”,请参考下面的MSDN中的STARTUPINFO结构体的说明
http://www.cnblogs.com/shanzy/articles/513455.html
7. 上面的crt0.c文件中涉及到MS针对不同的CPU厂商都能够跑MS的VC编译器的CPU假设,如下面MSDN文章所说------------当然,你也可以在代码中手写下面这些MS预定义宏,或者写MAKEFILE
Predefined Macros
The compiler recognizes six predefined ANSI C macros (see Table 1.1), and the Microsoft C++ implementation provides several more (see Table 1.2). These macros take no arguments and cannot be redefined. Their value (except for __LINE__ and __FILE__) must be constant throughout compilation. Some of the predefined macros listed below are defined with multiple values. Their values can be set by selecting the corresponding menu option in the Visual C++ development environment, or by using a command-line switch. See the tables below for more information.
Table 1.1 ANSI Predefined Macros
| Macro | Description | 
| __DATE__ | The compilation date of the current source file. The date is a string literal of the form Mmm dd yyyy. The month name Mmm is the same as for dates generated by the library function asctime declared in TIME.H. | 
| __FILE__ | The name of the current source file. __FILE__ expands to a string surrounded by double quotation marks. | 
| __LINE__ | The line number in the current source file. The line number is a decimal integer constant. It can be altered with a #line directive. | 
| __STDC__ | Indicates full conformance with the ANSI C standard. Defined as the integer constant 1 only if the /Za compiler option is given and you are not compiling C++ code; otherwise is undefined. | 
| __TIME__ | The most recent compilation time of the current source file. The time is a string literal of the form hh:mm:ss. | 
| __TIMESTAMP__ | The date and time of the last modification of the current source file, expressed as a string literal in the form Ddd Mmm Date hh:mm:ss yyyy, where Ddd is the abbreviated day of the week and Date is an integer from 1 to 31. | 
Table 1.2 Microsoft-Specific Predefined Macros
| Macro | Description | 
| _CHAR_UNSIGNED | Default char type is unsigned. Defined when /J is specified. | 
| __cplusplus | Defined for C++ programs only. | 
| _CPPRTTI | Defined for code compiled with /GR (Enable Run-Time Type Information). | 
| _CPPUNWIND | Defined for code compiled with /GX (Enable Exception Handling). | 
| _DLL | Defined when /MD or /MDd (Multithread DLL) is specified. | 
| _M_ALPHA | Defined for DEC ALPHA platforms. It is defined as 1 by the ALPHA compiler, and it is not defined if another compiler is used. | 
| _M_IX86 | Defined for x86 processors. See Table 1.3 for more details. | 
| _M_MPPC | Defined for Power Macintosh platforms. Default is 601 (/QP601). See Table 1.4 for more details. | 
| _M_MRX000 | Defined for MIPS platforms. Default is 4000 (/QMR4000). See Table 1.5 for more details. | 
| _M_PPC | Defined for PowerPC platforms. Default is 604 (/QP604). See Table 1.6 for more details. | 
| _MFC_VER | Defines the MFC version. Defined as 0x0421 for Microsoft Foundation Class Library 4.21. Always defined. | 
| _MSC_EXTENSIONS | This macro is defined when compiling with the /Ze compiler option (the default). Its value, when defined, is 1. | 
| _MSC_VER | Defines the compiler version. Defined as 1200 for Microsoft Visual C++ 6.0. Always defined. | 
| _MT | Defined when /MD or /MDd (Multithreaded DLL) or /MT or /MTd (Multithreaded) is specified. | 
| _WIN32 | Defined for applications for Win32®. Always defined. | 
As shown in following tables, the compiler generates a value for the preprocessor identifiers that reflect the processor option specified.
| Option in Developer Studio | Command-Line Option | Resulting Value | 
| Blend | /GB | _M_IX86 = 500 (Default. Future compilers will emit a different value to reflect the dominant processor.) | 
| Pentium | /G5 | _M_IX86 = 500 | 
| Pentium Pro | /G6 | _M_IX86 = 600 | 
| 80386 | /G3 | _M_IX86 = 300 | 
| 80486 | /G4 | _M_IX86 = 400 | 
| Option in development environment | Command-Line Option | Resulting Value | 
| PowerPC 601 | /QP601 | _M_MPPC = 601 (Default) | 
| PowerPC 603 | /QP603 | _M_MPPC = 603 | 
| PowerPC 604 | /QP604 | _M_MPPC = 604 | 
| PowerPC 620 | /QP620 | _M_MPPC = 620 | 
Table 1.5 Values for _M_MRX000
| Option in Developer Studio | Command-Line Option | Resulting Value | 
| R4000 | /QMR4000 | _M_MRX000 = 4000 (Default) | 
| R4100 | /QMR4100 | _M_MRX000 = 4100 | 
| R4200 | /QMR4200 | _M_MRX000 = 4200 | 
| R4400 | /QMR4400 | _M_MRX000 = 4400 | 
| R4600 | /QMR4600 | _M_MRX000 = 4600 | 
| R10000 | /QMR10000 | _M_MRX000 = 10000 | 
| Option in Developer Studio | Command-Line Option | Resulting Value | 
| PowerPC 601 | /QP601 | _M_PPC = 601 | 
| PowerPC 603 | /QP603 | _M_PPC = 603 | 
| PowerPC 604 | /QP604 | _M_PPC = 604 (Default) | 
| PowerPC 620 | /QP620 | _M_PPC = 620 | 
8. 任何C/C++编译器的构造,都是依托于ANSI C/ANSI C++标准的,但是,由于某些历史问题当ANSI标准影响了厂商的标准,或者厂商认为某些东西更利于开发的时候,厂商会在ANSI标准提供的编译器的基础上对CRT运行时库进行扩充,扩充的结果就是上面的情况
9. 厂商扩充了ANSI标准,就需要写出一个自己的编译器(MS 的VC编译器就是cl.exe),写这个cl.exe的过程要根据厂商扩充之后的各种标准表格,在写这个cl.exe的时候做出很多的选择分支(当然,MS这里用它认为重要的一些“自定义宏”来写它的cl.exe)
 
                    
                     
                    
                 
                    
                


 
         
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号