2010-08-12 20 views

Respuesta

23

Finalmente es el sistema operativo. Generalmente hay algún medio entre el punto de entrada real y la función principal, esto se inserta mediante el compilador .

Algunos detalles (relacionados con Windows): Hay un encabezado en el archivo PE llamado IMAGE_OPTIONAL_HEADER que tiene el campo AddressOfEntryPoint, que a su vez es la dirección del primer byte de código en el archivo que se ejecutará.

+1

No es insertado por el compilador, es insertado por el enlazador, usualmente enlazando a algo como 'crt.a (crt .o) 'o' crt.lib (crt.obj) ', que generalmente forma parte de algo como' libc.a' o 'c.lib'. –

+0

@ChristianHujer tienes razón, por compilador quise decir bien la cadena de herramientas. – Andrey

+0

estás seguro acerca de __linker__, supongo que qué __loader__ hace entonces? – roottraveller

38

El sistema operativo llama a la función main(). En realidad, generalmente llama a algo más llamado algo extraño como _init. El compilador de C vincula una biblioteca estándar a cada aplicación que proporciona este punto de entrada definido por el sistema operativo y luego llama al main().

Editar: Obviamente, eso no era lo suficientemente detallado y correcto para algunas personas.

El Executable and Linkable Format (ELF) que muchos sistemas operativos Unix definen como una dirección de punto de entrada. Ahí es donde el programa comienza a ejecutarse después de que el sistema operativo finaliza su llamada exec(). En un sistema Linux esto es _init.

De -d objdump:

Disassembly of section .init: 

08049f08 <_init>: 
8049f08:  55      push %ebp 
8049f09:  89 e5     mov %esp,%ebp 
8049f0b:  83 ec 08    sub $0x8,%esp 
8049f0e:  e8 a1 05 00 00   call 804a4b4 <call_gmon_start> 
8049f13:  e8 f8 05 00 00   call 804a510 <frame_dummy> 
8049f18:  e8 d3 50 00 00   call 804eff0 <__do_global_ctors_aux> 
8049f1d:  c9      leave 
8049f1e:  c3      ret  

De -d readelf:

0x00000001 (NEEDED)      Shared library: [libstdc++.so.6] 
0x00000001 (NEEDED)      Shared library: [libm.so.6] 
0x00000001 (NEEDED)      Shared library: [libgcc_s.so.1] 
0x00000001 (NEEDED)      Shared library: [libpthread.so.0] 
0x00000001 (NEEDED)      Shared library: [libc.so.6] 
0x0000000c (INIT)      0x8049f08 
0x0000000d (FINI)      0x804f018 
0x00000004 (HASH)      0x8048168 
0x00000005 (STRTAB)      0x8048d8c 
0x00000006 (SYMTAB)      0x804867c 
0x0000000a (STRSZ)      3313 (bytes) 
0x0000000b (SYMENT)      16 (bytes) 
0x00000015 (DEBUG)      0x0 
0x00000003 (PLTGOT)      0x8059114 
0x00000002 (PLTRELSZ)     688 (bytes) 
0x00000014 (PLTREL)      REL 
0x00000017 (JMPREL)      0x8049c58 
0x00000011 (REL)      0x8049be0 
0x00000012 (RELSZ)      120 (bytes) 
0x00000013 (RELENT)      8 (bytes) 
0x6ffffffe (VERNEED)     0x8049b60 
0x6fffffff (VERNEEDNUM)     3 
0x6ffffff0 (VERSYM)      0x8049a7e 
0x00000000 (NULL)      0x0 

Se puede ver que INIT es igual a la dirección de _init.

El código para frame_dummy y __do_global_ctors_aux está en un conjunto de archivos llamados crtbegin.o y crtend.o (y variantes de esos nombres). Estos son parte de GCC. Ese código hace varias cosas necesarias para un programa C, como la configuración de stdin, stdout, variables globales y estáticas y otras cosas.

El siguiente artículo describe bastante bien lo que hace en Linux (tomado de una respuesta más abajo con menos votos): http://dbp-consulting.com/tutorials/debugging/linuxProgramStartup.html

creo que otra persona de respuesta ya se ha descrito lo que hace de Windows.

+2

'__start', woo. – strager

+4

no llama a '_init' ni a ningún otro. llama a la dirección del punto de entrada. puede estar en cualquier lado – Andrey

+0

NECESARIO libstdC++. So.6? ¡Esto no es de un programa C! – Jens

4

Tenga en cuenta que además de las respuestas ya publicado, también es posible que usted pueda llamar main mismo. En general, esta es una mala idea reservada para el código ofuscado.

+4

Esto no es legal en C++, por cierto, una forma más en la que C++ no es un superconjunto estricto. –

6

El sistema operativo se llama main. Habrá una dirección en el ejecutable reubicable que apunta a la ubicación de main (Ver el ABI de Unix para más información).

Pero, ¿quién llama al sistema operativo?

La unidad de procesamiento central, en la señal "RESET" (que también se activa al encender), comenzará a buscar en alguna ROM en una dirección determinada (por ejemplo, 0xffff) sus instrucciones.

Normalmente habrá algún tipo de instrucción de salto en el BIOS, que configura los chips de memoria configurados, los controladores básicos del disco duro cargados, etc., etc.Luego se lee el sector de arranque del disco duro y se inicia el siguiente gestor de arranque, que carga el archivo que contiene la información básica de cómo leer, por ejemplo, una partición NTFS y cómo leer el archivo kernel. El entorno del kernel se configurará, se cargará el kernel, y luego - y luego! - se saltará el núcleo para su ejecución.

Después de todo ese trabajo duro que se ha hecho, el núcleo puede proceder a cargar nuestro software.

5

El sistema operativo llama a una función incluida en el tiempo de ejecución de C (CRT) y está vinculada a su ejecutable. Llamar a esto "CRT principal".

CRT main hace algunas cosas, las dos más importantes, al menos en C++, son ejecutar una variedad de clases globales de C++ y llamar a sus constructores, y llamar a su función main() y dar su retorno valor para el shell.

La fuente CRT principal de Visual C++ hace algunas cosas más, si la memoria sirve. Configura el asignador de memoria, importante si se usa Debug CRT para ayudar a encontrar fugas de memoria o malos accesos. También llama a main dentro de un controlador structured exception que atrapa el acceso a memoria defectuosa y otros bloqueos y los muestra.

+0

Aunque estás hablando de C++ no C, ¡tu publicación es esclarecedora! –

Cuestiones relacionadas