C++在嵌入式系统中的应用 --可以到10000分

时间:2022-04-25 19:54:26
我一直用C写嵌入式应用,现想改用C++,不知谁有支持C++的标准库,使程序的链接不依赖系统的默认库,我使用VC6.0环境及其编译器.或有这方面的资料。
相当实现mainCRTStartup()到main()之间的代码。
在它的实现中有        /*
         * do initializations
         */
        _initterm( __xi_a, __xi_z );

        /*
         * do C++ initializations
         */
        _initterm( __xc_a, __xc_z );

请问在编译中它的参数值是如何确定的?

26 个解决方案

#1


你只要不调用库就行啦,连stl也不用试试。

#2


实现进入main()之前的例程,简单说全局类的构造函数在从何时调用,怎样调用

#3


main只是形式而已。

你真有10000分?羡慕

#4


全局类的构造函数在main()之前调用,调用顺序未定义;调用后会把析构函数压入
全局堆栈中,main()之后弹出并析构先前构造的;给你的建议是,不要在全局类中
调用其它全局类,包括cout等标准库

#5


我的可用分多的很!!

mainCRTStartup()为装载后的入口函数,它的运行体在CRT0中有源,我用的如下:
        if ( !_heap_init(0) )               /* initialize heap */
            fast_error_exit(_RT_HEAPINIT);  /* write message and die */

            _ioinit();                      /* initialize lowio */

            /* get cmd line info */
            _acmdln = (char *)GetCommandLineA();

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

            _setargv();
            _setenvp();

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

            __initenv = _environ;
            mainret = main(__argc, __argv, _environ);

            exit(mainret);
}
而_cinit ()中的函数基本为
       _initterm( __xi_a, __xi_z );

        /*
         * do C++ initializations
         */
        _initterm( __xc_a, __xc_z );

其实__cx_a,__xc_z就是全局类的解析函数,我不知它是如何生成的。如果我对这部分代码进行重写,该如何处理?









}

#6


如果是在嵌入式系统中,这两个例程可以不理睬,它主要是在系统内存中构筑上下文,将应用程序在系统堆中注册,嵌入式程序可以不用考虑,直接用NOP填入就行了!!!
用反汇编看一下!!!

#7


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;
}

#8


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;

#9


谢谢你们的回复!!
其实我用的是586的嵌入式微控制器,在应用中我从第一条指令就开始接管(0xfffffff0),以后所有的都自己完成。所以不能用任何库。我用VC作为开发工具,它编译出来的PE格式也是自己装载的,当然还包括解压(像Linux内核装载),现在想改用C++,也只是借助VC编译器及环境。

#10


wei的答复部分可能与我的有些出入。当一C++文件编译后,如果有全局变量,会存在一个段CRT$XCU,这一段其实是包含了类的初始化代码的,它还会调用_atexit函数,而该函数是将该全局类的析构函数放入一全局函数数组中,供程序退出时调用。
我对CRT$XCU还没进行分析,不知该段在Linker时如何处理,当系统Loader 该EXE对该段是如何处理的(如对BSS段的特殊处理)。
我在程序中内存的管理(如delete,new)也是自己处理的,程序的装载点是在0x1000上,

#11


gz

#12


楼主在那里?我现在的下项目也是用从C++,在arm下。不过我作应用程序的编制,我刚学嵌入式编程不久,很希望同你探讨!

#13


up

#14


用gcc的编译器,他可以指定不链接启动代码和标准库,但是静态全局变量的初始化依旧保证进行。不需要操心。
VC的话我很少用,不知道有没有开关可以控制这一点,不过我很怀疑。

#15


一起讨论吧

#16


从程序启动入口到main()这一段代码是编译器实现相关的;就是说,楼主费了很大力气反汇编然后跟踪出来的东东很可能会随时变化。

不明白,为什么楼主认为在嵌入式环境中就不能用任何库。如果标准库也不用,使用c++又有什么优势?而且可能一些运行时机制,比如RTTI,exception之类的东东也是以库的形式被连接进来的(不知道VC的具体情况,只能说可能)。 我认为只要在最后联接好的最终PE格式的EXE文件,不依赖任何一个DLL,就应该没有问题了。象STL,string之类的东东你尽管用好了。。。 :)

一点建议仅供参考

#17


另外,gcc也是不错的选择

#18


个人看法:现在用c++搞嵌入式开发不太成熟。
哪一天有嵌入式系统开发平台还差不多

#19


一个字,牛

#20


高手,牛!

#21


不想用默认库,链接时加参数-nodefaultlib也许可以。

#22


#23


TO:  magic007(无名)
哪一天有嵌入式系统开发平台还差不多
******************************
中国人太懒了   一用就用windows  一说就是office   总之 就是用别人开发的东西

该醒醒了     

外国学生 一学c用的是在 unix 下的   

现在  linux占外国用的系统比例已经有  40%上了   就是咱们中国用的microsoft多   !!

努力吧!

#24


学习

#25


一直想看到楼主的回复~~ 是不是不来了?

#26


楼主:我也用c做嵌入式开发,不过刚开始,指点一下吧。
      dongchange@eyou.com

#1


你只要不调用库就行啦,连stl也不用试试。

#2


实现进入main()之前的例程,简单说全局类的构造函数在从何时调用,怎样调用

#3


main只是形式而已。

你真有10000分?羡慕

#4


全局类的构造函数在main()之前调用,调用顺序未定义;调用后会把析构函数压入
全局堆栈中,main()之后弹出并析构先前构造的;给你的建议是,不要在全局类中
调用其它全局类,包括cout等标准库

#5


我的可用分多的很!!

mainCRTStartup()为装载后的入口函数,它的运行体在CRT0中有源,我用的如下:
        if ( !_heap_init(0) )               /* initialize heap */
            fast_error_exit(_RT_HEAPINIT);  /* write message and die */

            _ioinit();                      /* initialize lowio */

            /* get cmd line info */
            _acmdln = (char *)GetCommandLineA();

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

            _setargv();
            _setenvp();

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

            __initenv = _environ;
            mainret = main(__argc, __argv, _environ);

            exit(mainret);
}
而_cinit ()中的函数基本为
       _initterm( __xi_a, __xi_z );

        /*
         * do C++ initializations
         */
        _initterm( __xc_a, __xc_z );

其实__cx_a,__xc_z就是全局类的解析函数,我不知它是如何生成的。如果我对这部分代码进行重写,该如何处理?









}

#6


如果是在嵌入式系统中,这两个例程可以不理睬,它主要是在系统内存中构筑上下文,将应用程序在系统堆中注册,嵌入式程序可以不用考虑,直接用NOP填入就行了!!!
用反汇编看一下!!!

#7


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;
}

#8


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;

#9


谢谢你们的回复!!
其实我用的是586的嵌入式微控制器,在应用中我从第一条指令就开始接管(0xfffffff0),以后所有的都自己完成。所以不能用任何库。我用VC作为开发工具,它编译出来的PE格式也是自己装载的,当然还包括解压(像Linux内核装载),现在想改用C++,也只是借助VC编译器及环境。

#10


wei的答复部分可能与我的有些出入。当一C++文件编译后,如果有全局变量,会存在一个段CRT$XCU,这一段其实是包含了类的初始化代码的,它还会调用_atexit函数,而该函数是将该全局类的析构函数放入一全局函数数组中,供程序退出时调用。
我对CRT$XCU还没进行分析,不知该段在Linker时如何处理,当系统Loader 该EXE对该段是如何处理的(如对BSS段的特殊处理)。
我在程序中内存的管理(如delete,new)也是自己处理的,程序的装载点是在0x1000上,

#11


gz

#12


楼主在那里?我现在的下项目也是用从C++,在arm下。不过我作应用程序的编制,我刚学嵌入式编程不久,很希望同你探讨!

#13


up

#14


用gcc的编译器,他可以指定不链接启动代码和标准库,但是静态全局变量的初始化依旧保证进行。不需要操心。
VC的话我很少用,不知道有没有开关可以控制这一点,不过我很怀疑。

#15


一起讨论吧

#16


从程序启动入口到main()这一段代码是编译器实现相关的;就是说,楼主费了很大力气反汇编然后跟踪出来的东东很可能会随时变化。

不明白,为什么楼主认为在嵌入式环境中就不能用任何库。如果标准库也不用,使用c++又有什么优势?而且可能一些运行时机制,比如RTTI,exception之类的东东也是以库的形式被连接进来的(不知道VC的具体情况,只能说可能)。 我认为只要在最后联接好的最终PE格式的EXE文件,不依赖任何一个DLL,就应该没有问题了。象STL,string之类的东东你尽管用好了。。。 :)

一点建议仅供参考

#17


另外,gcc也是不错的选择

#18


个人看法:现在用c++搞嵌入式开发不太成熟。
哪一天有嵌入式系统开发平台还差不多

#19


一个字,牛

#20


高手,牛!

#21


不想用默认库,链接时加参数-nodefaultlib也许可以。

#22


#23


TO:  magic007(无名)
哪一天有嵌入式系统开发平台还差不多
******************************
中国人太懒了   一用就用windows  一说就是office   总之 就是用别人开发的东西

该醒醒了     

外国学生 一学c用的是在 unix 下的   

现在  linux占外国用的系统比例已经有  40%上了   就是咱们中国用的microsoft多   !!

努力吧!

#24


学习

#25


一直想看到楼主的回复~~ 是不是不来了?

#26


楼主:我也用c做嵌入式开发,不过刚开始,指点一下吧。
      dongchange@eyou.com