Поскольку вы конкретно упоминается «К концу дня мне нужно превратить мой C код на языке, который конкретно мой процессор должен понять,» Я объясню немного о том, как компиляторы работы.
Типичные компиляторы делают несколько вещей.
Во-первых, они делают что-то, называемое лексированием. Этот шаг принимает индивидуальные символы и объединяет их в «токены», которые понимаются на следующем шаге. Этот шаг различает языковые слова (например, «для» и «если» в C), операторы (например, «+»), константы (например, целые и строковые литералы) и другие. То, что он отличает, зависит от самого языка.
Следующий шаг - это синтаксический анализатор, который берет поток токенов, создаваемых лексером, и (обычно) преобразует его во что-то, называемое «Абстрактное синтаксическое дерево», или AST. AST представляет собой вычисления, выполненные программой, с структурами данных, которые может перемещаться компилятором. Обычно AST не зависит от языка, а компиляторы, такие как GCC, могут анализировать разные языки в общем формате AST, который может понять следующий шаг (генератор кода).
Наконец, код-генератор проходит через AST и выводит код, который представляет семантику AST, то есть код, который фактически выполняет вычисления, которые представляет AST.
В случае GCC и, возможно, других компиляторов компилятор фактически не создает машинный код. Вместо этого он выводит код сборки, который он передает ассемблеру. Ассемблер проходит аналогичный процесс лексинга, разбора и генерации кода для создания машинного кода. В конце концов, ассемблер - это просто компилятор, который компилирует ассемблерный код.
В случае С (и многих других) Ассемблер обычно не является последним шагом. Ассемблер создает объекты, называемые объектными файлами, которые содержат нерешенные ссылки на функции в других объектных файлах или библиотеках (например, printf в стандартной библиотеке C или функции из других файлов C в вашем проекте). Эти объектные файлы передаются тому, что называется «компоновщик», задачей которого является объединение всех объектных файлов в один двоичный файл и разрешение всех нерешенных ссылок в объектных файлах.
Наконец, после всех этих шагов у вас есть полный исполняемый двоичный файл.
Обратите внимание на то, что GCC и многие, многие другие компиляторы работают, но это не обязательно так. Любая программа, которую вы могли бы написать, которая точно принимает поток кода C и выводит поток другого кода (сборка, машинный код, даже javascript), который является эквивалентным, является компилятором.
Кроме того, этапы не всегда полностью раздельны.Вместо того, чтобы лексировать и весь файл, затем анализируя весь результат, затем генерируя код для всего АСТ, компилятор может выполнить немного лексинга, затем начать разбор, когда он имеет некоторые токены, а затем вернуться к лексированию, когда парсеру требуется больше токенов , Когда синтаксический анализатор чувствует, что он знает достаточно, он может генерировать код, прежде чем лексер произведет для него еще несколько токенов.
** как ** - сборщик, ** ld ** - линкер, GCC поставляется с теми –
Пожалуйста, смотрите следующее: http://stackoverflow.com/questions/6264249/how-does-the-compilation-linking- process-work – Sajidkhan
gcc dont конвертировать C непосредственно в сборку. Это даст вам лучшую идею: http://en.wikipedia.org/wiki/GNU_Compiler_Collection#GENERIC_and_GIMPLE – sunny1304