КАК УСТРОЕНО ВСЁ - приложение B

Компилятор: как текст программы становится инструкциями процессора

Путь от строчки кода до машинных команд - и почему этот перевод устроен именно так

Мы разобрали, как процессор выполняет инструкции - одну за другой, такт за тактом. Инструкции эти закодированы числами: конкретными битовыми последовательностями, которые конкретный процессор понимает как «сложи», «сравни», «перейди по адресу». Но программисты не пишут числа. Они пишут текст - на языках вроде Python, C или Java. Как текст превращается в числа, которые понимает процессор?

📝 Две крайности: что такое исходный код

Любая программа начинается как текстовый файл - исходный код. Это обычные буквы и символы, которые человек может прочитать и понять. Строчка x = a + b - человеку понятна. Процессору - нет. Процессор понимает только свои инструкции в двоичном виде, и «сложи содержимое регистра 2 с содержимым регистра 3» выглядит для него как цепочка битов, а не как текст.

Между человеческим текстом и машинными командами нужен переводчик. Исторически сложились два принципиально разных подхода к этому переводу - компиляция и интерпретация.

🏭 Компилятор: перевод заранее

Компилятор - это программа, которая читает весь исходный код целиком и заранее, до запуска, переводит его в машинные инструкции. Результат - отдельный файл: исполняемый файл, который процессор может запустить напрямую. На Windows такие файлы имеют расширение .exe.

Аналогия: представьте, что вы заказали перевод книги с японского. Переводчик садится, читает книгу от начала до конца, переводит весь текст и отдаёт вам готовую русскую версию. Теперь вы читаете русскую книгу - переводчик больше не нужен, он своё дело сделал. Именно так работает компиляция: программист один раз компилирует код, а пользователи запускают уже готовый исполняемый файл без каких-либо промежуточных шагов.

Языки C, C++, Go и Rust работают именно так. Скомпилированная программа запускается быстро - процессор получает команды напрямую, без посредников.

📌 Что компилятор делает внутри: Компиляция - это не просто «заменить слова числами». Компилятор анализирует структуру программы, проверяет логику, находит ошибки ещё до запуска и активно оптимизирует код: переставляет инструкции, убирает лишние вычисления, подбирает наиболее эффективные команды процессора для каждой операции. Хороший компилятор нередко делает программу быстрее, чем если бы программист писал машинный код вручную.

🎭 Интерпретатор: перевод на ходу

Интерпретатор работает иначе: он читает исходный код и выполняет его строчка за строчкой прямо во время запуска. Никакого предварительного перевода нет - интерпретатор всегда присутствует рядом и на каждом шаге говорит процессору, что делать дальше.

Та же аналогия с книгой: теперь переводчик сидит рядом и переводит устно, по одной странице за раз, пока вы слушаете. Вам не нужно ждать, пока переведут всю книгу, - можно начать сразу. Но переводчик нужен при каждом чтении, и скорость ограничена его темпом работы.

Python, JavaScript в браузере и PHP - интерпретируемые языки. Запустить скрипт на Python просто: не нужна компиляция, можно сразу запустить и увидеть результат. Именно поэтому Python так популярен для обучения и быстрых экспериментов. Плата за это - скорость: интерпретируемый код работает медленнее скомпилированного, потому что между программой и процессором всегда стоит посредник.

⚡ JIT: лучшее из двух миров

Разработчики давно заметили проблему: компиляция быстра в работе, но требует отдельного шага перед запуском; интерпретация удобна, но медленна. Решение - JIT-компиляция (Just-In-Time, «точно в нужный момент»).

JIT-компилятор начинает как интерпретатор - запускает программу сразу, без предварительной подготовки. Но параллельно следит, какие участки кода выполняются часто. Как только он замечает «горячий» фрагмент - цикл, который повторяется тысячи раз, - он компилирует именно его в машинные инструкции прямо во время работы программы. При следующем обращении этот участок уже выполняется напрямую, без интерпретатора.

Именно так работает JavaScript в современных браузерах: Chrome и Firefox используют мощные JIT-компиляторы, которые делают JavaScript сопоставимым по скорости с компилируемыми языками для большинства задач. Java и Python 3.13+ тоже используют JIT.

💡 Байт-код - промежуточное звено: Многие языки используют хитрый компромисс. Java, например, компилируется не в машинный код конкретного процессора, а в байт-код - промежуточный формат для виртуальной машины Java (JVM). Байт-код - это не двоичные инструкции реального процессора, а инструкции выдуманного универсального процессора. JVM уже переводит их в инструкции реального железа - и может делать это с JIT-оптимизацией. Главный выигрыш: один и тот же .jar-файл запускается на Windows, Linux и macOS без перекомпиляции. «Напиши один раз - запусти везде» - лозунг Java с 1995 года.

🔧 Почему программы не работают на чужом процессоре

Здесь кроется важное следствие из всего сказанного. Когда компилятор переводит код в машинные инструкции - он переводит их в инструкции конкретной архитектуры. Программа, скомпилированная под x86 (Intel и AMD), содержит инструкции x86. Процессор ARM их не поймёт - у него другой «язык».

Именно поэтому программы для Windows не запускаются на macOS напрямую - дело не только в операционной системе, но и в том, что Mac на Apple Silicon использует архитектуру ARM, а большинство Windows-программ скомпилировано под x86. И именно поэтому при скачивании программы иногда предлагают выбрать версию: «Windows x64», «macOS Apple Silicon», «Linux ARM» - это разные скомпилированные файлы для разных процессоров.

Подход Как работает Скорость Примеры языков
Компиляция Весь код переводится заранее, результат - готовый исполняемый файл Максимальная C, C++, Go, Rust
Интерпретация Код выполняется строчка за строчкой во время запуска Медленнее Python, PHP, старый JavaScript
Байт-код + JVM Компиляция в промежуточный формат, JVM переводит в реальные инструкции Хорошая, переносимая Java, Kotlin, Scala
JIT-компиляция Интерпретация с динамической компиляцией горячих участков Близко к компилируемым JavaScript (V8), Python 3.13+

🔗 Как это связано с тем, что мы уже знаем

Теперь полная картина замыкается. Программист пишет текст на языке высокого уровня. Компилятор переводит его в инструкции конкретного процессора - те самые числа, которые процессор читает в цикле «выбрать - декодировать - исполнить». Операционная система загружает скомпилированный файл в память, создаёт процесс и передаёт управление первой инструкции. Дальше - миллиарды тактов, регистры, кэш, шины, и на экране появляется результат.

Между «написал код» и «процессор выполнил инструкцию» - несколько уровней перевода и абстракции. Компилятор - один из них. И именно он позволяет людям писать понятным языком, пока железо работает числами.


ANY.BY

Нужна помощь с техникой? Привозите - диагностика при заказе ремонта бесплатна. Контакты и запись.