Ответы:
=====> COMPILATION PROCESS <======
|
|----> Input is Source file(.c)
|
V
+=================+
| |
| C Preprocessor |
| |
+=================+
|
| ---> Pure C file ( comd:cc -E <file.name> )
|
V
+=================+
| |
| Lexical Analyzer|
| |
+-----------------+
| |
| Syntax Analyzer |
| |
+-----------------+
| |
| Semantic Analyze|
| |
+-----------------+
| |
| Pre Optimization|
| |
+-----------------+
| |
| Code generation |
| |
+-----------------+
| |
| Post Optimize |
| |
+=================+
|
|---> Assembly code (comd: cc -S <file.name> )
|
V
+=================+
| |
| Assembler |
| |
+=================+
|
|---> Object file (.obj) (comd: cc -c <file.name>)
|
V
+=================+
| Linker |
| and |
| loader |
+=================+
|
|---> Executable (.Exe/a.out) (com:cc <file.name> )
|
V
Executable file(a.out)
Предварительная обработка C - это первый шаг в компиляции. Он обрабатывает:
#define
заявления.#include
заявления.Назначение модуля - преобразовать исходный файл C в файл кода Pure C.
В блоке шесть шагов:
Он объединяет символы в исходном файле, чтобы сформировать «ТОКЕН». Токен - это набор символов, в котором нет «пробела», «табуляции» и «новой строки». Поэтому эта единица компиляции также называется «TOKENIZER». Он также удаляет комментарии, генерирует таблицы символов и записи таблицы перемещений.
Этот модуль проверяет синтаксис в коде. Например:
{
int a;
int b;
int c;
int d;
d = a + b - c * ;
}
Приведенный выше код сгенерирует ошибку синтаксического анализа, поскольку уравнение не сбалансировано. Этот модуль проверяет это внутренне, создавая дерево синтаксического анализатора следующим образом:
=
/ \
d -
/ \
+ *
/ \ / \
a b c ?
Поэтому это устройство также называется ПАРСЕР.
Этот блок проверяет смысл утверждений. Например:
{
int i;
int *p;
p = i;
-----
-----
-----
}
Приведенный выше код генерирует ошибку «Присвоение несовместимого типа».
Этот блок не зависит от процессора, т. Е. Существует два типа оптимизации.
Этот модуль оптимизирует код в следующих формах:
Например:
{
int a = 10;
if ( a > 5 ) {
/*
...
*/
} else {
/*
...
*/
}
}
Здесь компилятор знает значение 'a' во время компиляции, поэтому он также знает, что условие if всегда истинно. Следовательно, в коде исключается часть else.
Например:
{
int a, b, c;
int x, y;
/*
...
*/
x = a + b;
y = a + b + c;
/*
...
*/
}
можно оптимизировать следующим образом:
{
int a, b, c;
int x, y;
/*
...
*/
x = a + b;
y = x + c; // a + b is replaced by x
/*
...
*/
}
Например:
{
int a;
for (i = 0; i < 1000; i++ ) {
/*
...
*/
a = 10;
/*
...
*/
}
}
В приведенном выше коде, если 'a' является локальным и не используется в цикле, его можно оптимизировать следующим образом:
{
int a;
a = 10;
for (i = 0; i < 1000; i++ ) {
/*
...
*/
}
}
Здесь компилятор генерирует ассемблерный код, чтобы наиболее часто используемые переменные сохранялись в регистрах.
Здесь оптимизация зависит от ЦП. Предположим, что если в коде более одного перехода, они преобразуются в один следующим образом:
-----
jmp:<addr1>
<addr1> jmp:<addr2>
-----
-----
Элемент управления переходит непосредственно к.
Затем последняя фаза - это компоновка (которая создает исполняемый файл или библиотеку). Когда исполняемый файл запускается, загружаются необходимые библиотеки.
Представление ASCII:
[Source Code] ---> Compiler ---> [Object code] --*
|
[Source Code] ---> Compiler ---> [Object code] --*--> Linker --> [Executable] ---> Loader
| |
[Source Code] ---> Compiler ---> [Object code] --* |
| |
[Library file]--* V
[Running Executable in Memory]
Надеюсь, это поможет вам еще немного.
Сначала просмотрите эту диаграмму:
(img source->internet)
Вы делаете фрагмент кода и сохраняете файл (Исходный код), затем
Предварительная обработка : - Как следует из названия, это не часть компиляции. Они инструктируют компилятор выполнить необходимую предварительную обработку перед фактической компиляцией. Вы можете назвать эту фазу подстановкой текста или интерпретацией специальных директив препроцессора, обозначенных #.
Компиляция : - Компиляция - это процесс, в котором программа, написанная на одном языке, переводится на другой целевой язык. Если есть какие-то ошибки, компилятор обнаружит их и сообщит об этом.
Сборка : - Код сборки переводится в машинный код. Вы можете назвать ассемблер особым типом компилятора.
Связывание : - Если для этого фрагмента кода требуется связать какой-либо другой исходный файл, компоновщик свяжет их, чтобы сделать его исполняемым файлом.
После этого происходит много процессов. Да, как вы уже догадались, здесь роль загрузчика:
Загрузчик : - загружает исполняемый код в память; программа и стек данных создаются, регистр инициализируется.
Маленькая дополнительная информация: - http://www.geeksforgeeks.org/memory-layout-of-c-program/ , там вы можете увидеть схему памяти.
Компилятор: это программа, которая переводит программу на языке высокого уровня в программу на машинном языке. Компилятор умнее ассемблера. Он проверяет всевозможные пределы, диапазоны, ошибки и т. Д. Но время выполнения его программы больше и занимает большую часть памяти. У него низкая скорость. Потому что компилятор просматривает всю программу, а затем переводит всю программу в машинные коды. Если компилятор работает на компьютере и создает машинные коды для того же компьютера, то он называется самокомпилятором или резидентным компилятором. С другой стороны, если компилятор работает на компьютере и производит машинные коды для другого компьютера, то он известен как кросс-компилятор.
Компоновщик: в языках высокого уровня хранятся некоторые встроенные файлы заголовков или библиотеки. Эти библиотеки предопределены и содержат основные функции, которые необходимы для выполнения программы. Эти функции связаны с библиотеками программой под названием Linker. Если компоновщик не находит библиотеку функции, он сообщает компилятору, а затем компилятор выдает ошибку. Компилятор автоматически вызывает компоновщик на последнем этапе компиляции программы. Не встроенные в библиотеки, он также связывает пользовательские функции с пользовательскими библиотеками. Обычно более длинная программа делится на более мелкие подпрограммы, называемые модулями. И эти модули должны быть объединены для выполнения программы. Процесс объединения модулей выполняется компоновщиком.
Загрузчик: Загрузчик - это программа, которая загружает машинные коды программы в системную память. В вычислительной технике загрузчик - это часть операционной системы, которая отвечает за загрузку программ. Это один из важнейших этапов в процессе запуска программы. Потому что он помещает программы в память и подготавливает их к выполнению. Загрузка программы включает чтение содержимого исполняемого файла в память. По завершении загрузки операционная система запускает программу, передав управление загруженному программному коду. Все операционные системы, поддерживающие загрузку программ, имеют загрузчики. Во многих операционных системах загрузчик постоянно находится в памяти.
В Википедии должен быть хороший ответ, вот мои мысли:
*
*
Компоновщики и загрузчики из LinuxJournal ясно объясняют эту концепцию. Это также объясняет, как появилось классическое название a.out. (вывод на ассемблере)
Краткое изложение,
c program --> [compiler] --> objectFile --> [linker] --> executable file (say, a.out)
у нас есть исполняемый файл, теперь отдайте этот файл своему другу или клиенту, который нуждается в этом программном обеспечении :)
когда они запускают это программное обеспечение, скажем, введя его в командной строке ./a.out
execute in command line ./a.out --> [Loader] --> [execve] --> program is loaded in memory
Как только программа загружена в память, управление передается этой программе, заставляя ПК (счетчик программ) указывать на первую инструкцию a.out
Он будет читать исходный файл, который может иметь тип .c, .cpp и т. Д., И переводить его в файл .o, называемый объектным файлом.
Он объединяет несколько файлов .o, которые могут быть созданы для нескольких исходных файлов, в исполняемый файл (формат ELF в GCC). Есть два типа связывания:
Программа, загружающая исполняемый файл в основную память машины.
Для более подробного изучения этих трех этапов выполнения программы в Linux, пожалуйста, прочтите это .
компилятор изменений проверяет исходный код на наличие ошибок и превращает его в объектный код. это код, который запускает операционная система.
Часто вы не пишете всю программу в одном файле, поэтому компоновщик связывает все ваши файлы объектного кода.
ваша программа не будет выполняться, если она не находится в основной памяти
Компоновщик и интерпретатор - взаимоисключающие интерпретаторы, которые построчно получают код и выполняют построчно.
Компилятор Преобразует исходный код в объектный код.
Компоновщик Он объединяет несколько объектных файлов в один исполняемый файл программы.
Загрузчик Загружает исполняемый файл в основную память.
Компилятор - это специальная программа, которая обрабатывает операторы, написанные на определенном языке программирования, и превращает их в машинный язык или «код», который использует процессор компьютера.
Компилятор переводит строки кода с языка программирования на машинный язык.
Компоновщик создает связь между двумя программами.
Загрузчик загружает программу в память в основной базе данных, программе и т. Д.
Компилятор: это системное программное обеспечение, которое исправляет ошибки программ, объектного файла, сообщений и т. Д.
Компоновщик: это системное программное обеспечение, которое объединяет один или несколько объектных файлов и, возможно, некоторый библиотечный код либо в некоторую существующую библиотеку, либо в список ошибок.
Загрузчик: программа, которая загружает исполняемый файл в основную память машины.