Title.ru

Я ищу более техническое объяснение, чем ОС вызывает функцию. Может ли кто-нибудь помочь мне или указать на веб-сайт или книгу?

Ответов (6)

Решение

Файл .exe (или его аналог на других платформах) содержит адрес «точки входа». В первом приближении ОС загружает соответствующие разделы файла .EXE в оперативную память, а затем переходит к точке входа.

Как уже говорили другие, эта точка входа не будет `` основной '', а вместо этого будет частью библиотеки времени выполнения - она ​​будет выполнять такие действия, как инициализация статических объектов, настройка параметров argc / argv, настройка stdin / stdout / stderr и т. д. Когда все это будет сделано, она вызовет вашу функцию main (). Когда main завершается, среда выполнения проходит аналогичный процесс передачи вашего кода возврата обратно в среду, вызов статических деструкторов, вызов подпрограмм _atexit и т. Д.

Если у вас есть инструменты MS (возможно, не бесплатные), тогда у вас есть весь исходный код времени выполнения, и простой способ взглянуть на него - поставить точку останова на закрывающей скобке вашего метода main () и сделать один шаг назад. во время выполнения.

main() является частью библиотеки C и не является системной функцией. Я не знаю, что такое OS X или Linux, но Windows обычно запускает программу с расширением WinMainCRTStartup() . Этот символ запускает ваш процесс, извлекает аргументы командной строки, среду ( argc, argv, end ) и вызовы main() . Он также отвечает за вызов любого кода, который должен выполняться после main(), например atexit() .

Заглянув в свой файл Visual Studio, вы сможете найти реализацию по умолчанию, WinMainCRTStartup чтобы увидеть, что она делает.

Вы также можете определить собственную функцию для вызова при запуске, это делается путем изменения «точки входа» в параметрах компоновщика. Часто это функция, которая не принимает аргументов и возвращает пустоту.

Expert C++ / CLI (см. Страницу 279) содержит очень конкретные детали различных сценариев начальной загрузки для собственных, смешанных и чистых сборок CLR.

Это зависит от ОС. В OS X в заголовке mach есть кадр, который содержит начальный адрес регистра EIP (указателя команд).

После загрузки двоичного файла ОС запускает выполнение с этого адреса:

cristi: тестовое описание $ otool -l ./a.out | grep -A 10 LC_UNIXTHREAD
        cmd LC_UNIXTHREAD
    размер 80
     аромат i386_THREAD_STATE
      подсчитать i386_THREAD_STATE_COUNT
[..]
        ss 0x00000000 eflags 0x00000000 eip 0x00001f8c cs 0x00000000
[..]

Адрес - это адрес "стартовой" функции из двоичного файла:

cristi: test diciu $ нм ./a.out
0000200c D _NXArgc
00002008 D _NXArgv
00002000 D ___ имя программы
00001fe0 т __dyld_func_lookup
00001000 A __mh_execute_header
[..]
00001f8c T начало

В Mac OS X сначала вызывается функция start, даже перед функцией main:

(gdb) b начало
Точка останова 1 на 0x1f90
(gdb) b main
Точка останова 2 на 0x1ff4
(gdb) r
Стартовая программа: /Users/diciu/Programming/test/a.out 
Чтение символов для разделяемых библиотек ++. сделано

Точка останова 1, 0x00001f90 в start ()

Что касается окон, то функции точки входа:

  • Консоль: void __cdecl mainCRTStartup( void ) {}
  • GUI: void __stdcall WinMainCRTStartup( void ) {}
  • DLL: BOOL __stdcall _DllMainCRTStartup(HINSTANCE hinstDLL,DWORD fdwReason,void* lpReserved) {}

Единственная причина использовать их вместо обычного main / WinMain / DllMain - это если вы хотите использовать свою собственную библиотеку времени выполнения (если вам нужен меньший размер файла или пользовательские функции)

Информацию о пользовательских реализациях среды выполнения и других приемах для получения файлов PE меньшего размера см. В следующих разделах:

Если вас интересует книга, связанная с Windows и Win32 API, попробуйте

«Программирование приложений для Microsoft Windows» Джеффри Рихтера.