相当实现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分?羡慕
你真有10000分?羡慕
#4
全局类的构造函数在main()之前调用,调用顺序未定义;调用后会把析构函数压入
全局堆栈中,main()之后弹出并析构先前构造的;给你的建议是,不要在全局类中
调用其它全局类,包括cout等标准库
全局堆栈中,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就是全局类的解析函数,我不知它是如何生成的。如果我对这部分代码进行重写,该如何处理?
}
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;
}
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;
//==========================================
// 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编译器及环境。
其实我用的是586的嵌入式微控制器,在应用中我从第一条指令就开始接管(0xfffffff0),以后所有的都自己完成。所以不能用任何库。我用VC作为开发工具,它编译出来的PE格式也是自己装载的,当然还包括解压(像Linux内核装载),现在想改用C++,也只是借助VC编译器及环境。
#10
wei的答复部分可能与我的有些出入。当一C++文件编译后,如果有全局变量,会存在一个段CRT$XCU,这一段其实是包含了类的初始化代码的,它还会调用_atexit函数,而该函数是将该全局类的析构函数放入一全局函数数组中,供程序退出时调用。
我对CRT$XCU还没进行分析,不知该段在Linker时如何处理,当系统Loader 该EXE对该段是如何处理的(如对BSS段的特殊处理)。
我在程序中内存的管理(如delete,new)也是自己处理的,程序的装载点是在0x1000上,
我对CRT$XCU还没进行分析,不知该段在Linker时如何处理,当系统Loader 该EXE对该段是如何处理的(如对BSS段的特殊处理)。
我在程序中内存的管理(如delete,new)也是自己处理的,程序的装载点是在0x1000上,
#11
gz
#12
楼主在那里?我现在的下项目也是用从C++,在arm下。不过我作应用程序的编制,我刚学嵌入式编程不久,很希望同你探讨!
#13
up
#14
用gcc的编译器,他可以指定不链接启动代码和标准库,但是静态全局变量的初始化依旧保证进行。不需要操心。
VC的话我很少用,不知道有没有开关可以控制这一点,不过我很怀疑。
VC的话我很少用,不知道有没有开关可以控制这一点,不过我很怀疑。
#15
一起讨论吧
#16
从程序启动入口到main()这一段代码是编译器实现相关的;就是说,楼主费了很大力气反汇编然后跟踪出来的东东很可能会随时变化。
不明白,为什么楼主认为在嵌入式环境中就不能用任何库。如果标准库也不用,使用c++又有什么优势?而且可能一些运行时机制,比如RTTI,exception之类的东东也是以库的形式被连接进来的(不知道VC的具体情况,只能说可能)。 我认为只要在最后联接好的最终PE格式的EXE文件,不依赖任何一个DLL,就应该没有问题了。象STL,string之类的东东你尽管用好了。。。 :)
一点建议仅供参考
不明白,为什么楼主认为在嵌入式环境中就不能用任何库。如果标准库也不用,使用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多 !!
努力吧!
哪一天有嵌入式系统开发平台还差不多
******************************
中国人太懒了 一用就用windows 一说就是office 总之 就是用别人开发的东西
该醒醒了
外国学生 一学c用的是在 unix 下的
现在 linux占外国用的系统比例已经有 40%上了 就是咱们中国用的microsoft多 !!
努力吧!
#24
学习
#25
一直想看到楼主的回复~~ 是不是不来了?
#26
楼主:我也用c做嵌入式开发,不过刚开始,指点一下吧。
dongchange@eyou.com
dongchange@eyou.com
#1
你只要不调用库就行啦,连stl也不用试试。
#2
实现进入main()之前的例程,简单说全局类的构造函数在从何时调用,怎样调用
#3
main只是形式而已。
你真有10000分?羡慕
你真有10000分?羡慕
#4
全局类的构造函数在main()之前调用,调用顺序未定义;调用后会把析构函数压入
全局堆栈中,main()之后弹出并析构先前构造的;给你的建议是,不要在全局类中
调用其它全局类,包括cout等标准库
全局堆栈中,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就是全局类的解析函数,我不知它是如何生成的。如果我对这部分代码进行重写,该如何处理?
}
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;
}
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;
//==========================================
// 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编译器及环境。
其实我用的是586的嵌入式微控制器,在应用中我从第一条指令就开始接管(0xfffffff0),以后所有的都自己完成。所以不能用任何库。我用VC作为开发工具,它编译出来的PE格式也是自己装载的,当然还包括解压(像Linux内核装载),现在想改用C++,也只是借助VC编译器及环境。
#10
wei的答复部分可能与我的有些出入。当一C++文件编译后,如果有全局变量,会存在一个段CRT$XCU,这一段其实是包含了类的初始化代码的,它还会调用_atexit函数,而该函数是将该全局类的析构函数放入一全局函数数组中,供程序退出时调用。
我对CRT$XCU还没进行分析,不知该段在Linker时如何处理,当系统Loader 该EXE对该段是如何处理的(如对BSS段的特殊处理)。
我在程序中内存的管理(如delete,new)也是自己处理的,程序的装载点是在0x1000上,
我对CRT$XCU还没进行分析,不知该段在Linker时如何处理,当系统Loader 该EXE对该段是如何处理的(如对BSS段的特殊处理)。
我在程序中内存的管理(如delete,new)也是自己处理的,程序的装载点是在0x1000上,
#11
gz
#12
楼主在那里?我现在的下项目也是用从C++,在arm下。不过我作应用程序的编制,我刚学嵌入式编程不久,很希望同你探讨!
#13
up
#14
用gcc的编译器,他可以指定不链接启动代码和标准库,但是静态全局变量的初始化依旧保证进行。不需要操心。
VC的话我很少用,不知道有没有开关可以控制这一点,不过我很怀疑。
VC的话我很少用,不知道有没有开关可以控制这一点,不过我很怀疑。
#15
一起讨论吧
#16
从程序启动入口到main()这一段代码是编译器实现相关的;就是说,楼主费了很大力气反汇编然后跟踪出来的东东很可能会随时变化。
不明白,为什么楼主认为在嵌入式环境中就不能用任何库。如果标准库也不用,使用c++又有什么优势?而且可能一些运行时机制,比如RTTI,exception之类的东东也是以库的形式被连接进来的(不知道VC的具体情况,只能说可能)。 我认为只要在最后联接好的最终PE格式的EXE文件,不依赖任何一个DLL,就应该没有问题了。象STL,string之类的东东你尽管用好了。。。 :)
一点建议仅供参考
不明白,为什么楼主认为在嵌入式环境中就不能用任何库。如果标准库也不用,使用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多 !!
努力吧!
哪一天有嵌入式系统开发平台还差不多
******************************
中国人太懒了 一用就用windows 一说就是office 总之 就是用别人开发的东西
该醒醒了
外国学生 一学c用的是在 unix 下的
现在 linux占外国用的系统比例已经有 40%上了 就是咱们中国用的microsoft多 !!
努力吧!
#24
学习
#25
一直想看到楼主的回复~~ 是不是不来了?
#26
楼主:我也用c做嵌入式开发,不过刚开始,指点一下吧。
dongchange@eyou.com
dongchange@eyou.com