Вопрос:
со ссылкой на: http://www.cplusplus.com/articles/2v07M4Gy/
На этапе компиляции
Эта фаза преобразует программу в низкоуровневый код уровня сборки. Компилятор принимает предварительно обработанный файл (без каких-либо директив) и генерирует объектный файл, содержащий код уровня сборки. Теперь созданный объектный файл находится в двоичной форме. В созданном объектном файле каждая строка описывает одну инструкцию уровня машинного уровня низкого уровня.
Теперь, если я прав, разные архитектуры процессоров работают на разных языках/синтаксисе ассемблера.
Мой вопрос: как компилятор узнает, какой синтаксис языка ассемблера должен быть изменен? Другими словами, как компилятор С++ знает, какая архитектура процессора существует в машине, на которой он работает?
Существует ли какое-либо сопоставление, используемое ассемблером w.r.t архитектуры ЦП для генерации кода сборки для разных архитектур процессора?
N.S: Я новичок!
Лучший ответ:
Каждый компилятор должен быть “портирован” в данную систему. Для каждой поддерживаемой системы “порт компилятора” должен быть запрограммирован кем-то, кто знает систему в глубину.
Ответ №1
ПРЕДУПРЕЖДЕНИЕ: это чрезвычайно упрощено
Короче говоря, в компиляторе есть три основные части:
-
“Front-end”: эта часть читает язык (в данном случае С++) и преобразует его в своего рода псевдокод, специфичный для компилятора. (Абстрактное синтаксическое дерево или AST)
-
“Оптимизатор/средний конец”: эта часть принимает AST и делает оптимизированную с учетом архитектуры архитектуру.
-
“Back-end”: эта часть принимает AST и преобразует ее в двоичный исполняемый код, специфичный для архитектуры, на которой вы хотите скомпилировать свой язык.
Когда вы загружаете компилятор С++ для своей платформы, вы, например, загружаете интерфейс С++ с помощью бэкэнда linux-amd64, например.
Эта архитектура кодирования чрезвычайно полезна, поскольку она позволяет переносить компилятор для другой архитектуры без перезаписи всей синтаксической разборки/оптимизации. Это также позволяет кому-то создавать другой оптимизатор или даже другой интерфейс, поддерживающий совершенно другой язык, и, пока он выводит правильный АСТ, он будет совместим с каждым бэкэндом, когда-либо написанным для этого компилятора.
Ответ №2
Проще говоря, знание целевой системы закодировано в компиляторе.
Итак, у вас может быть компилятор C, который генерирует двоичные файлы SPARC и компилятор C, который генерирует двоичные файлы VAX. Они оба принимают один и тот же язык ввода (как определено в стандарте C), но производят от него разные программы.
Часто мы просто ссылаемся на “компилятор”, то есть на тот, который будет генерировать двоичные файлы для нашей текущей среды.
В наше время различие стало менее очевидным в сборниках компиляторов, таких как GCC. Теперь “разные компиляторы” часто являются одной и той же программой компилятора, просто настроенной с различными конфигурациями (это “файлы описания цели” ).
Ответ №3
Просто чтобы ответить на следующие вопросы:
Целевая архитектура действительно закодирована в конкретный экземпляр компилятора, который вы используете. Это важно также для процесса, называемого “кросс-компиляция”. Процесс компиляции в определенной системе исполняемого файла, который будет работать с другой системой/архитектурой.
Рассмотрите возможность работы с встроенной системой на кристалле, которая использует совершенно другой набор команд, чем ваш собственный. Вы работаете с системой x86/64 Linux, но вам нужно скомпилировать мобильное приложение, работающее на микропроцессоре ARM, или какой-либо другой тип архитектуры сборки.
Было бы нецелесообразно компилировать ваш код в целевой системе, который может быть настолько ограничен в ЦП и в памяти, что он не может реально запустить компилятор – и поэтому вы можете использовать порт GCC (или любой другой компилятор) для этой целевой архитектуры на вашей любимой системе.
Также очень важно помнить, что целая цепочка инструментов часто совместима с целевой системой, например, когда в нее вступают общие библиотеки, такие как libc, поскольку целевая ОС может быть другой версией Linux и будет иметь разные версии общих функций. В этом случае обычно используется цепочки инструментов, которые содержат все необходимые библиотеки и используют что-то вроде chroot или mock для компиляции в “целевой среде” из вашей системы.