Figure 1 Hello World .MAP File

    Address         Publics by Value             Rva+Base     Lib:Object
    0001:00000000   _main                        00401000 f   hello.obj
    0001:0000000c   _printf                      0040100c f   LIBC:printf.obj
    0001:0000003d   _mainCRTStartup              0040103d f   LIBC:crt0.obj
    0001:0000011c   __amsg_exit                  0040111c f   LIBC:crt0.obj
    0001:00000165   __stbuf                      00401165 f   LIBC:_sftbuf.obj
    0001:000001f2   __ftbuf                      004011f2 f   LIBC:_sftbuf.obj
    0001:0000022f   __output                     0040122f f   LIBC:output.obj
    0001:00000a39   ___initstdio                 00401a39 f   LIBC:_file.obj
    0001:00000ade   ___endstdio                  00401ade f   LIBC:_file.obj
    0001:00000af2   __cinit                      00401af2 f   LIBC:crt0dat.obj
    0001:00000b1f   _exit                        00401b1f f   LIBC:crt0dat.obj
    0001:00000b30   __exit                       00401b30 f   LIBC:crt0dat.obj
    0001:00000bf4   __XcptFilter                 00401bf4 f   LIBC:winxfltr.obj
    0001:00000d78   __setenvp                    00401d78 f   LIBC:stdenvp.obj
    0001:00000e31   __setargv                    00401e31 f   LIBC:stdargv.obj
    0001:0000107e   ___crtGetEnvironmentStringsA 0040207e f   LIBC:a_env.obj
    0001:000011b0   __ioinit                     004021b0 f   LIBC:ioinit.obj
    0001:0000135b   __heap_init                  0040235b f   LIBC:heapinit.obj
    0001:00001398   __global_unwind2             00402398 f   LIBC:exsup.obj
    0001:000013da   __local_unwind2              004023da f   LIBC:exsup.obj
    0001:00001432   __NLG_Return2                00402432 f   LIBC:exsup.obj
    0001:00001442   __abnormal_termination       00402442 f   LIBC:exsup.obj
    0001:00001465   __NLG_Notify1                00402465 f   LIBC:exsup.obj
    0001:0000146e   __NLG_Notify                 0040246e f   LIBC:exsup.obj
    0001:00001481   __NLG_Dispatch               00402481 f   LIBC:exsup.obj
    0001:00001490   __except_handler3            00402490 f   LIBC:exsup3.obj
    0001:0000154d   __seh_longjmp_unwind@4       0040254d f   LIBC:exsup3.obj
    0001:00001568   __FF_MSGBANNER               00402568 f   LIBC:crt0msg.obj
    0001:000015a1   __NMSG_WRITE                 004025a1 f   LIBC:crt0msg.obj
    0001:000016f4   _malloc                      004026f4 f   LIBC:malloc.obj
    0001:00001706   __nh_malloc                  00402706 f   LIBC:malloc.obj
    0001:00001732   __heap_alloc                 00402732 f   LIBC:malloc.obj
    0001:00001768   __isatty                     00402768 f   LIBC:isatty.obj
    0001:0000178e   _fflush                      0040278e f   LIBC:fflush.obj
    0001:000017c9   __flush                      004027c9 f   LIBC:fflush.obj
    0001:00001825   __flushall                   00402825 f   LIBC:fflush.obj
    0001:000018a0   _strlen                      004028a0 f   LIBC:strlen.obj
    0001:0000191b   _wctomb                      0040291b f   LIBC:wctomb.obj
    0001:00001990   __aulldiv                    00402990 f   LIBC:ulldiv.obj
    0001:00001a00   __aullrem                    00402a00 f   LIBC:ullrem.obj
    0001:00001a75   __flsbuf                     00402a75 f   LIBC:_flsbuf.obj
    0001:00001b8a   _calloc                      00402b8a f   LIBC:calloc.obj
    0001:00001c07   __fcloseall                  00402c07 f   LIBC:closeall.obj
    0001:00001c5f   _free                        00402c5f f   LIBC:free.obj
    0001:00001c90   _strcpy                      00402c90 f   LIBC:strcat.obj
    0001:00001ca0   _strcat                      00402ca0 f   LIBC:strcat.obj
    0001:00001d80   __setmbcp                    00402d80 f   LIBC:mbctype.obj
    0001:00002144   ___initmbctable              00403144 f   LIBC:mbctype.obj
    0001:00002160   _memcpy                      00403160 f   LIBC:memcpy.obj
    0001:00002495   ___sbh_heap_init             00403495 f   LIBC:sbheap.obj
    0001:000024d3   ___sbh_find_block            004034d3 f   LIBC:sbheap.obj
    0001:000024fe   ___sbh_free_block            004034fe f   LIBC:sbheap.obj
    0001:00002829   ___sbh_alloc_block           00403829 f   LIBC:sbheap.obj
    0001:00002b32   ___sbh_alloc_new_region      00403b32 f   LIBC:sbheap.obj
    0001:00002be3   ___sbh_alloc_new_group       00403be3 f   LIBC:sbheap.obj
    0001:00002cde   ___crtMessageBoxA            00403cde f   LIBC:crtmbox.obj
    0001:00002d70   _strncpy                     00403d70 f   LIBC:strncpy.obj
    0001:00002e6e   __callnewh                   00403e6e f   LIBC:handler.obj
    0001:00002e89   __commit                     00403e89 f   LIBC:commit.obj
    0001:00002ee0   __write                      00403ee0 f   LIBC:write.obj
    0001:0000308d   __fptrap                     0040408d f   LIBC:crt0fp.obj
    0001:00003096   __lseek                      00404096 f   LIBC:lseek.obj
    0001:00003130   __getbuf                     00404130 f   LIBC:_getbuf.obj
    0001:00003180   _memset                      00404180 f   LIBC:memset.obj
    0001:000031d8   _fclose                      004041d8 f   LIBC:fclose.obj
    0001:0000322e   ___crtLCMapStringA           0040422e f   LIBC:a_map.obj
    0001:0000347d   ___crtGetStringTypeA         0040447d f   LIBC:a_str.obj
    0001:000035d0   _memmove                     004045d0 f   LIBC:memmove.obj
    0001:00003905   __free_osfhnd                00404905 f   LIBC:osfinfo.obj
    0001:0000397f   __get_osfhandle              0040497f f   LIBC:osfinfo.obj
    0001:000039bc   __dosmaperr                  004049bc f   LIBC:dosmap.obj
    0001:00003a23   __close                      00404a23 f   LIBC:close.obj
    0001:00003ad6   __freebuf                    00404ad6 f   LIBC:_freebuf.obj
    0001:00003b10   __alloca_probe               00404b10 f   LIBC:chkstk.obj
    0001:00003b10   __chkstk                     00404b10 f   LIBC:chkstk.obj

Figure 2 PRINTF.CPP

    //==========================================
    // LIBCTINY - Matt Pietrek 2001
    // MSDN Magazine, January 2001
    //==========================================
    #include <windows.h>
    #include <stdio.h>
    #include <stdarg.h>

    // Force the linker to include USER32.LIB
    #pragma comment(linker, "/defaultlib:user32.lib")

    extern "C" int __cdecl printf(const char * format, ...)
    {
      char szBuff[1024];
      int retValue;
      DWORD cbWritten;
      va_list argptr;

      va_start( argptr, format );
      retValue = wvsprintf( szBuff, format, argptr );
      va_end( argptr );

      WriteFile(  GetStdHandle(STD_OUTPUT_HANDLE), szBuff, retValue,
                  &cbWritten, 0 );

      return retValue;
    }

Figure 3 INITTERM

    //==========================================
    // LIBCTINY - Matt Pietrek 2001
    // MSDN Magazine, January 2001
    //==========================================
    #include <windows.h>
    #include <malloc.h>
    #include "initterm.h"

    #pragma data_seg(".CRT$XCA")
    _PVFV __xc_a[] = { NULL };

    #pragma data_seg(".CRT$XCZ")
    _PVFV __xc_z[] = { NULL };

    #pragma data_seg()  /* reset */

    #pragma comment(linker, "/merge:.CRT=.data")

    typedef void (__cdecl *_PVFV)(void);

    void __cdecl _initterm (
            _PVFV * pfbegin,
            _PVFV * pfend
            )
    {
      /*
       * walk the table of function pointers from the bottom up, until
       * the end is encountered.  Do not skip the first entry.  The initial
       * value of pfbegin points to the first valid entry.  Do not try to
       * execute what pfend points to.  Only entries before pfend are
       * valid.
       */
      while ( pfbegin < pfend )
      {
        // if current table entry is non-NULL, call thru it.
        if ( *pfbegin != NULL )
          (**pfbegin)();
        ++pfbegin;
      }
    }

    static _PVFV * pf_atexitlist = 0;
    static unsigned max_atexitlist_entries = 0;
    static unsigned cur_atexitlist_entries = 0;

    void __cdecl _atexit_init(void)
    {
      max_atexitlist_entries = 32;
      pf_atexitlist = (_PVFV *)calloc( max_atexitlist_entries,
                                       sizeof(_PVFV*) );
    }

    int __cdecl atexit (_PVFV func )
    {
      if ( cur_atexitlist_entries < max_atexitlist_entries )
      {
        pf_atexitlist[cur_atexitlist_entries++] = func;
        return 0;
      }

      return -1;
    }

    void __cdecl _DoExit( void )
    {
      if ( cur_atexitlist_entries )
      {
        _initterm( pf_atexitlist,
                   // Use ptr math to find the end of the array
                   pf_atexitlist + cur_atexitlist_entries );
      }
    }

Figure 4 DLLCRTO.CPP

    //==========================================
    // LIBCTINY - Matt Pietrek 2001
    // MSDN Magazine, January 2001
    // FILE: DLLCRT0.CPP
    //==========================================
    #include <windows.h>
    #include "initterm.h"

    // Force the linker to include KERNEL32.LIB
    #pragma comment(linker, "/defaultlib:kernel32.lib")

    // Force 512 byte section alignment in the PE file
    #pragma comment(linker, "/OPT:NOWIN98")

    // #pragma comment(linker, "/nodefaultlib:libc.lib")
    // #pragma comment(linker, "/nodefaultlib:libcmt.lib")

    // User routine DllMain is called on all notifications

    extern BOOL WINAPI DllMain(
                               HANDLE  hDllHandle,
                               DWORD   dwReason,
                               LPVOID  lpreserved
                               ) ;

    //
    // Modified version of the Visual C++ startup code.  Simplified to
    // make it easier to read.  Only supports ANSI programs.
    //
    extern "C"
    BOOL WINAPI _DllMainCRTStartup(
                                   HANDLE  hDllHandle,
                                   DWORD   dwReason,
                                   LPVOID  lpreserved
                                   )
    {
      if ( dwReason == DLL_PROCESS_ATTACH )
      {
        // set up our minimal cheezy atexit table
        _atexit_init();

        // Call C++ constructors
        _initterm( __xc_a, __xc_z );
      }

      BOOL retcode = DllMain(hDllHandle, dwReason, lpreserved);

      if ( dwReason == DLL_PROCESS_DETACH )
      {
        _DoExit();
      }

      return retcode ;
    }

Figure 5 TEST.CPP

    // Small test program to exercise TINYCRT.  Does nothing useful
    //
    #include <windows.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>

    int main( int argc, char *argv[] )
    {
      int i;

      for ( i = 0; i < argc; i++ )
      {
        printf( "argc: %u \'%s\'\n", i, argv[i] );
      }

      char * p = new char[10];
      lstrcpy( p, "Hello" );
      delete p;

      printf( "%s\n", strlwr( "MyLowerCaseString" ) );
      printf ( "strcmpi: %u\n", strcmpi( "Abc", "abc" ) );
      strrchr( "foo", 'o' );

      return 0;
    }

    // Declare a simple C++ class with a constructor
    class TestClass
    {
    public:
      TestClass(void)
      {
        printf( "In TestClass constructor\n" );
      }
      ~TestClass(void)
      {
        printf( "In TestClass destructor\n" );
      }
    };

    // Create a global instance of the class
    TestClass g_TestClassInstance;