Процесс компиляции кода действительно интересен, поверьте мне. Сегодня мы сосредоточимся на процессе компиляции gcc и поймем, как файл с исходным кодом становится исполняемым файлом.
Процесс компиляции
Процесс компиляции включает четыре последовательных этапа. Чтобы перейти от исходной программы, написанной человеком, к исполняемому файлу, необходимо последовательно выполнить эти четыре этапа. В системах Unix/Linus коммандос gcc может выполнить весь процесс за один раз или шаг за шагом в соответствии с требованиями программиста.
Во-первых, нам нужен исходный файл c, и мы назовем его main.c. Это можно сделать следующим образом:
коснитесь main.c
Следующее, что нужно сделать, это отредактировать этот файл:
emacs main.c
Здесь нам нужна крутая программа:
#include‹stdio.h›
пустая функция()
{
printf("Привет, мир\n");
возврат (0);
}
Итак, если у нас есть исходный файл c, такой как main.c, и мы хотим, чтобы этот файл «превратился» в полноценный исполняемый файл, мы делаем:
$ gcc main.c
Да, это сделано. Смотреть:
$ ls
a.out main.c
$./a.out
Привет мир
Но то, что только что произошло, я имею в виду, за кулисами.
1. Предварительная обработка: исправление исходного кода.
На самом первом этапе программа C или исходный файл C предварительно обрабатывается препроцессором, и выполняются такие вещи, как удаление комментариев, расширение макросов и расширение включенных файлов.
На этом шаге компилятор получает промежуточный входной файл и начинает работу.
2. Компиляция: перевести в сборку.
Здесь компилятор преобразует файлы, сгенерированные препроцессором, в качестве входных данных и генерирует ассемблерный код. Этот код представляет собой вид кода, закодированного на языке программирования, который состоит из инструкций, являющихся мнемоническими кодами для соответствующих инструкций машинного языка. На этом этапе мы должны помнить, что компьютеры могут выполнять двоичный код или нулевой язык, а ассемблерный код еще не является кодом, который машины все понимают, поэтому работа еще не завершена. Далее следует преобразователь, который может преобразовать этот ассемблерный код в машинный код.
3. Сборка: сгенерируйте объектный код.
На этом этапе мы встречаемся с ассемблером, который преобразует ассемблерный код из последнего этапа в объектный код. Объектный код — это полностью распознаваемый и исполняемый машинный код.
4. Связывание: соберите все вместе.
На заключительном этапе компоновщик использует некоторые функции библиотек и связывает объектный код с этим кодом библиотеки и, наконец, генерирует исполняемый код типа .exe.
Следующее изображение суммирует весь процесс преобразования исходного файла в исполняемый файл.