Действительно ли C/C++ сначала компилируется в ассемблер?

Рейтинг: 2Ответов: 2Опубликовано: 14.01.2023

Часто вижу, что процесс компиляции описывают примерно так: сорс -> ассемблер -> объектный файл -> бинарный файл. Но в том же gcc для получения ассемблера надо указать дополнительный флаг, а объектный файл в любом случае будет. Правда ли, что этот флаг выполняет другую (отдельную) процедуру, а не просто останавливает этот конвейер на втором шаге? Т.е. действительно ли C/С++ код компилируется в ассемблер, а после этого в байткод? Или ассемблера вообще может не быть в процессе генерации бинаря, если не указать флаг?

P.S.: вопрос не про стандарт (с его т.з. может быть что угодно), а про реальные компиляторы (gcc, clang, msvc).

Ответы

▲ 1

gcc сначала делает ассемблер, а потом с помощью as получает из него машинный код. clang и msvc сразу получают машинный код без промежуточного ассемблера.

▲ -3

Начать нужно с основ. Есть два вида программ: в машинных кодах (бинарник, исполняемый файл и пр.) и не в машинных кодах. Программу в машинных кодах исполняет непосредственно процессор. Программу не в машинных кодах исполняет интерпретатор, или иная исполняющая система, которая сама является программой в машинных кодах (либо ещё одним интерпретатором, но в конце концов всё доходит до машинных кодов).

Изначально компиляцией называлось преобразование программы в машинных код. Сейчас к этому добавилось преобразование в байт-код или промежуточный код, который потом выполняется интерпретатором. Компилятор, как правило, использует промежуточные т. н. объектные файлы. Это связано исключительно с многомодульностью и использованием каких-либо библиотек.

Программа на ассеблере тоже компилируется в машинный код с использованием объектных файлов.

Примеры интерпретаторов: Питон, Руби, Ява-машина и пр. Обозреватель Интернета тоже является интерпретатором языка HTML и каких-то скриптовых языков. Может, при необходимости, подключать внешние интерпретаторы. Сам может быть как программой в машинных кодах, так и какой-то интерпретируемой программой.

Что касается компилятора C++. Генерация ассемблерного текста там - просто дополнительная опция.

И так, по пунктам:

  1. "Часто вижу, что процесс компиляции описывают примерно так: сорс -> ассемблер -> объектный файл -> бинарный файл" - Очевидно, это верно для языка C и компилятора gcc. Но для других компиляторов это может быть не так, ассемблер не является обязательным в этой цепочке.
  2. "Но в том же gcc для получения ассемблера надо указать дополнительный флаг, а объектный файл в любом случае будет" - похоже, что в качестве промежуточного языка согласно модели компилятора для C и gcc используется именно ассемблер.
  3. "Правда ли, что этот флаг выполняет другую (отдельную) процедуру, а не просто останавливает этот конвейер на втором шаге?" - нет.
  4. "Т.е. действительно ли C/С++ код компилируется в ассемблер, а после этого в байткод?" - для C и gcc да, но только не в байткод, а в машинный код.
  5. "вопрос не про стандарт (с его т.з. может быть что угодно), а про реальные компиляторы (gcc, clang, msvc)" - с другими компиляторами по-другому, как уже написали в комментариях.

Кстати, обратите вннимание, что assembler в буквальном переводе означает сборщик, то есть ассемблер - это язык для сборочных файлов. Скорее всего, когда-то так родилось, и с тех пор всё ещё используется в некоторых случаях. Большой проект мог быть написан на различных языках, потом он транслировался в ассемблер и потом собирался. А сейчас и памяти побольше, и дискового пространства, и технологии обработки информации усовершенствовались.