Какой механизм знает, что точка входа в программу является основной () - PullRequest
3 голосов
/ 11 февраля 2020

Как прикладная программа узнает, что ее точкой входа является функция main()?

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

В какой момент эта декларация фактически объявляется? Например, в C точка входа должна быть функцией main(). Кто предоставляет этот механизм программе? Операционная система или компилятор?

Я пришел к этому вопросу после разборки простого канонического примера «Hello World» в Visual Studio.

В этом коде всего несколько строк и функция main().

Но после его разборки в пространстве памяти появляется много определений и макросов, и main() - не единственное объявление и определение.

Здесь ниже скриншот разборки части. Я также знаю, что в определении языка существует строгое правило, согласно которому должна быть определена и существовать только одна main() функция.

Подводя итог моему вопросу: мне интересно, какой механизм направляет или устанавливает функцию main() в качестве записи точка прикладной программы.

enter image description here

1 Ответ

3 голосов
/ 12 февраля 2020

Приложение не знает, что main () является точкой входа. Прежде всего, мы предполагаем C не C ++ здесь, несмотря на вашу картинку.

Для C точка входа "C" main (). Но вы не можете просто начать выполнение там, так как у нас есть предположения, более того, правила, в C, что, например, .data нужно инициализировать и .bss обнулить.

unsigned x = 1;
unsigned int y;

Мы ожидаем, что когда основной () ударил, что х = 1. и большинство людей предполагают, и, возможно, указано, что y = 0 в то время, я бы не делал этого предположения, но в любом случае.

Нам также нужен указатель стека и нам нужно иметь дело с argc / argv. Если C ++, то другие вещи должны быть сделаны. Даже для C в зависимости.

ПРИЛОЖЕНИЕ, как правило, ничего этого не знает. Скорее всего, вы работаете с библиотекой C, и эта библиотека / должна отвечать за код bootstrap, предшествующий main (), а также за скрипт компоновщика для компоновщика, поскольку bootstrap и скрипт компоновщика тесно связаны между собой. И на основании некоторых реализаций можно утверждать, что библиотека C отделима от цепочки инструментов, поскольку мы знаем, что с помощью gnu вы можете выбирать из разных, и у них разные загрузочные скрипты и сценарии компоновщика. Но я уверен, что есть много тесно связанных между собой библиотек и операционной системы, так как многие C библиотечные вызовы заканчиваются одним или бесчисленными системными вызовами.

Вы разрабатываете Операционная система, часть дизайна операционной системы, предполагающая, что она поддерживает загружаемые приложения во время выполнения, представляет собой формат файла, который поддерживает загрузчик операционных систем, функции, которые хочет поддерживать загрузчик операционной системы, и то, как они пересекаются с форматом файла, что не редкость для ОС для определения формата файла, но с elf и другими (не случайно / независимо созданными, без сомнения) у вас есть возможность для новой ОС использовать существующий контейнер, такой как elf. Дизайн ОС и ее загрузчик определяют многое, и библиотека C, которая сопрягается со всем этим, должна следовать всем этим правилам, если она интегрирована в компилятор, то компилятор тоже должен играть.

Это не приложение, которое знает, что оно является частью дизайна системы, и приложение является просто рабом всего этого, когда вы компилируете на этой платформе для этой платформы все эти правила и отношения в игре Вы добавляете очень маленькую часть головоломки, остальное уже установлено, какие форматы файлов поддерживаются, для какого формата требуется какая информация, какие правила требуются для решения компилятора / библиотеки. Проект системы определяет, обнуляются ли .data и .bss загрузчиком или приложением, и что я имею в виду под bootstrap не пользовательской частью программы, вы не можете bootstrap C в C потому что для C потребуется bootstrap, а если бы bootstrap было в C, то C потребовалось бы bootstrap и т. д.

int main ( void )
{
    return 0;  
}

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

скомпилируйте эту программу на windows и linux и ma c и разных версиях каждой с разными компиляторами для каждой или C библиотек, и разными версиями каждой, et c. И то, что вы ожидаете увидеть, возможно, даже если тот же целевой ISA, даже тот же компьютер, некоторый процент комбинаций МОЖЕТ выбрать те же самые несколько инструкций для функции, то, что обернуто вокруг нее, может быть похожим, но не тем же , Не было бы повода удивляться, если некоторые реализации сильно отличаются друг от друга.

И это все для полнофункциональных операционных систем, которые загружают программы в ram и запускают их, поскольку встроенные объекты не удивляются, если различия еще больше. В полном объеме вы ожидаете увидеть MMU, и приложение получит, возможно, нулевое адресное пространство для .text, .data,. bss как минимум, поэтому у всех решений может быть любимое место или любимое количество разделов в одинаковом порядке в двоичном файле, но размер каждого может быть указан c для реализации. Порядок / размер могут варьироваться в зависимости от C версии библиотеки или версии компилятора и т. Д. c.

Маги c находятся в дизайне системы. и это не волхвы c, это дизайн. main () не может быть введен напрямую, и все еще имеют различные части языка, все еще работающие как .data и .bss init, указатель стека может быть решен до ввода, но как и где .data и .bss являются спецификацией приложения c, поэтому не может быть обработан простой ветвью на главном из ОС.

Компоновщик для вашей цепочки инструментов может быть различным образом определен, где находится точка входа, которую можно предположить / продиктовать для этого инструмента / цели или командной строки. опция или опция сценария компоновщика, или какой-то специальный символ, который вы наносите на ярлык, или то, что дизайнеры выбирают Предполагается, что main является точкой входа C, хотя на самом деле это не означает, что ей может быть какой-то код C, предшествующий ей, но в общем случае существует некоторое количество asm (cant bootstrap C с C) и затем один или несколько шагов к main ().

...