Вы сказали, что у вас есть базовое понимание того, что происходит, и затем спросите, что происходит. Итак, во-первых, это очень широкий / большой материал, чтобы действительно получить даже четырехлетний курс по электротехнике, он охватывает только набор инструментов, необходимых для начала, чтобы понять все. Ясно, что это не то, что подходит под любой SE-ответ (и я написал ответы, доказывающие, что для ответов существует ограничение по размеру / характеру).
Если вы хотите знать физическую электронику, тогда задача компиляциине имеет отношения к делу, не имеет отношения к этому вопросу.
Процессоры невероятно глупы, они представляют собой конечные автоматы, которые работают с входящими битами. Ваш компьютер имеет много уровней программного обеспечения, которые в некотором смысле скрывают физические элементы нижнего уровня, такие каквозможно, способы получить доступ к хранилищу, USB, PCI жестких дисков и так далее. Один USB, старая спецификация 1.1 была 300 печатных страниц. больше, чем здесь уместно, и это не распространяется на какие-либо подробности, касающиеся технологий флэш-памяти, ни USB, ни SATA, ни других.
процессор получает машинный код от запросов на своей шине, запросы на его шине декодируютсяконтроллером памяти или несколькими в зависимости от дизайна. Через несколько уровней обсуждения, которое могло бы уместиться в одном ответе, рассматриваются различные периферийные устройства, USB-контроллер, PCI-контроллер, DRAM-контроллер и т. д. Затем, обычно через контроллер PCIE, у вас есть жесткий диск или другие энергонезависимые носители в наши дни. поэтому очень большое количество инструкций обеспечивает уровень, который позволяет ядру получать доступ к конкретному жесткому диску, а также бесчисленное множество других файлов для создания файловой системы поверх хранения и извлечения битов с носителя.
Компилятор, ассемблер или компоновщик и т. Д. Станут еще одним уровнем программного обеспечения поверх уровней ядра / драйверов поверх уровней аппаратного обеспечения для доступа к байтам из файлов на носителе. в случае компилятора он считывает байты, считающиеся символами ascii, у него есть программное обеспечение, которое анализирует эти байты, декодирующие определенный язык, а затем, используя таблицы, обычно обрабатывает эту информацию, сокращая программу на более мелкие части.
x = y + 5;
у вас есть как минимум две переменные, которые требуют хранения (при условии отсутствия оптимизации, которая удаляет мертвый код, прежде чем вы сможете уменьшить мертвый код, вам все равно придется пройти через этопроцесс). таким образом, как минимум, должно быть чтение генерации переменной y для 5, этап сложения с некоторым промежуточным результатом и затем сохранение этого промежуточного результата в месте назначения. компилятор собирается перебирать такие строки кода, чтобы разбить его на эти типы операций.
тогда может быть шаг оптимизации, например, компилятор может понять, что нигде программа не использует переменную xпосле этой строки кода, так что эта строка кода не дает значения, это мертвый код, поэтому все шаги, связанные с этой строкой кода, могут пройти, оптимизироваться. сегодня это обычно делается в оперативной памяти, но могут быть созданы промежуточные файлы для хранения информации, которая будет обработана.
снова поймите, что весь этот код - это машинный код и данные, которые передаются по шинам, через кеши, из больших запоминающих устройств, вероятно, основанных на драмах, каждый из которых состоит из одного-многих семестров классов для полного понимания, понимания высокого уровняне так много.
интерфейс компилятора преобразует ASCII в какой-то внутренний язык / таблицы, средняя часть компилятора может / делает это дальше, оптимизирует и т. Д. В этот момент компилятор может сохранить промежуточный файлили один популярный компилятор имеет формат файла и двоичный формат, который можно скомпилировать на этом этапе, чтобы позднее выполнить внутреннее преобразование в целевой набор команд.
Бэкенд компилятора затем преобразует последовательности операций в серию инструкций, которые поддерживает цель. вы можете иметь или не иметь оптимизатор глазка, который является целевой оптимизацией, например, целевой набор команд может предлагать команду регистр = регистр + немедленная, где 5 - это скорее немедленная, чем регистр = 5;зарегистрироваться = зарегистрироваться + зарегистрироваться. как только это будет сделано, тогда вывод, который для здравого смысла является ассемблером, но есть компиляторы, которые выводят машинные / объектные файлы.
запись файла ascii - это просто запись байтов в файл, поэтому у вас есть аппаратные слои, слои операционной системы плюс слои языковых библиотек, а затем ваше приложение, которое выдает эквивалент fprintf () для выводасимволы ascii, представляющие язык ассемблера, включая метки и директивы. если объект и машинный код, то он почти идентичен с физической точки зрения, только генерируются разные байты, которые представляют формат объектного файла и машинный код.
ассемблер такой же, только немного проще, он также читает черезвсе слои, байты, которые являются символами ascii, анализируют их и т. д., будучи другим языком, больше ориентированы на метки и тому подобное, а также на отдельные инструкции, которые сообщают ассемблеру биты, которые следует использовать в машинном коде для строк, которые являются инструкциями. ассемблер снова использует временные файлы или таблицы в памяти, чтобы отслеживать эту информацию. сжатие данных отличается от компилятора, но все еще достаточно много работы, набор инструкций имеет относительные смещения, и вещи, которые необходимо вычислять, поскольку каждая инструкция начинает принимать расстояние от одной инструкции до многих, могут занять многоитерации.
и через программные слои ассемблер затем записывает объектный файл.
тогда компоновщик берет объектные файлы и некоторый набор правил, которые определяют физическое адресное пространство, по крайней мере, из представления вна этом этапе, начиная с окончательного выполнения программы, это, скорее всего, виртуальный адрес, но это адресное пространство, сообщаемое компоновщику каким-то образом, часто каким-то другим файлом в формате, который должен быть проанализирован как программа в таблицах и т. д. использование слоев программного и аппаратного обеспечения для получения байтов с носителя, составляющего этот скрипт компоновщика. затем компоновщик, используя все слои, считывает байты с носителей, которые являются объектами. внешние функции, например, между двумя, скажем, файлами .C, должны быть разрешены на этом этапе, так как компоновщик помещает объекты в виртуальную копию целевого пространства памяти, где каждая из этих меток наконец получает свой адрес, затем объекты, которые ссылаются наэта метка может быть исправлена компоновщиком, в зависимости от общей схемы набора инструментов, компоновщик иногда генерирует дополнительный код или создает / изменяет инструкции, оставленные ассемблером для облегчения этих соединений объектов.
И, как и все другие программы здесьон проходит через программный и аппаратный уровни, чтобы записать байты в файловую систему, которая в данном случае является конечным двоичным файлом, отмечая, что большую часть времени конечный двоичный файл представляет собой не просто образ памяти программы, которую нужно загрузить и запустить, он имеетфайловая структура, такая же, как файл документа или изображения, будет иметь некоторые накладные расходы, а также двоичные двоичные объекты, которые должны быть загружены в память для запуска создаваемой программы.