不同操作系统下的程序入口点分析

转自 http://hi.baidu.com/liu_bin0101/blog/item/03e3a9ec4e0fd5d72e2e21b9.html

程序入口与编译器没有什么关系, 关键是链接链接器(UNIX的用的ld和WINDOWS下用的LINK.EXE)
ld 用参数-e entry参数指定程序入口为entry
LINK.EXE 用/ENTRY:symbol指定程序入口为symbol
通常, ld/LINK.EXE 不是被直接运行的, 而是由编译器用适当的参数去调用的.
C/C++编译器的完成编译之后会用适当的参数去调用ld/LINK.EXE告诉链接器程序的入口.
WINDOWS下VC编译的程序程序入口点是WinMainCRTStartup(/SUBSYSTEM:WINDOWS, WIN32 GUI 程序)或mainCRTStartup(/SUBSYSTEM:CONSOLE 即WIN32控制台程序).
UNIX下cc/gcc设置的缺省程序入口是_start.

不论是WinMainCRTStartup, mainCRTStartup还是_start, 在链接器生成可执行程序之后, 入口点信息都保存在可执行文件中了.
WinMainCRTStartup, mainCRTStartup或_start函数都是由C标准库实现的, 这些里面通常做一些初始化工作, 包括一些需要用汇编语言才能完成的工作, 然后调用的main函数(WIN32 GUI 程序是WinMain).
这个过程可以用一个例子来说明, 下面是FreeBSD 6.2 的libc的crt1.c, 里面有_start函数的实现:
C/C++ code
    
    
/* LINTLIBRARY */ /* - * Copyright 1996-1998 John D. Polstra. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef lint #ifndef __GNUC__ #error "GCC is needed to compile this file" #endif #endif /* lint */ #include < stdlib.h > #include " libc_private.h " #include " crtbrand.c " extern int _DYNAMIC; #pragma weak _DYNAMIC typedef void ( * fptr)( void ); extern void _fini( void ); extern void _init( void ); extern int main( int , char ** , char ** ); extern void _start( char * , ...); #ifdef GCRT extern void _mcleanup( void ); extern void monstartup( void * , void * ); extern int eprol; extern int etext; #endif char ** environ; const char * __progname = "" ; static __inline fptr get_rtld_cleanup( void ) { fptr retval; #ifdef __GNUC__ __asm__( " movl %%edx,%0 " : " =rm " (retval)); #else retval = (fptr) 0 ; /* XXXX Fix this for other compilers */ #endif return (retval); } /* The entry function. */ void _start( char * ap, ...) { fptr cleanup; int argc; char ** argv; char ** env; const char * s; #ifdef __GNUC__ __asm__( " and $0xfffffff0,%esp " ); #endif cleanup = get_rtld_cleanup(); argv = & ap; argc = * ( long * )( void * )(argv - 1 ); env = argv + argc + 1 ; environ = env; if (argc > 0 && argv[ 0 ] != NULL) { __progname = argv[ 0 ]; for (s = __progname; * s != ' \0 ' ; s ++ ) if ( * s == ' / ' ) __progname = s + 1 ; } if ( & _DYNAMIC != NULL) atexit(cleanup); else _init_tls(); #ifdef GCRT atexit(_mcleanup); #endif atexit(_fini); #ifdef GCRT monstartup( & eprol, & etext); #endif _init(); exit( main(argc, argv, env) ); } #ifdef GCRT __asm__( " .text " ); __asm__( " eprol: " ); __asm__( " .previous " ); #endif __asm__( " .ident\t\"$FreeBSD: src/lib/csu/i386-elf/crt1.c,v 1.14 2005/05/19 07:36:07 dfr Exp $\" " );
至于楼主想知道的"如何让没有main函数的C程序变成可执行文件?" 涉及到自己链接给链接程序传参数, 有一个例子可以试试.
C/C++ code
      
      
/* - * name: entry_start.c * auth: mymtom * date: 2008-02-18 */ #include < unistd.h > #include < string .h > void _start( void ) { ( void )write( 1 , __func__, strlen(__func__)); ( void )write( 1 , " \n " , 1 ); _exit( 0 ); }

这个程序在FreeBSD 6.2 和Fedora Core 6上可以用下面的命令编译, 也可以运行.
gcc -c entry_start.c
ld -o entry_start -static -e _start entry_start.o -lc
但是在运行Loongson Debian Linux V4.0的龙芯福珑迷你(龙芯2E处理器)的机器上会core dump,
原因应该是没有初始化C运行环境而调用了C库函数引起的. 毕竟这不是写C程序的正规方法


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值