# Компилятор и декомпилятор **Компилятор - программа, переводящая написанный код на языке программирования высокого уровня в набор машинных кодов.** **Виды компиляторов:** - **Векторизующий.** Компилирует исходный код в машинный код для компьютеров, оснащённых векторным процессором. - **Гибкий.** Сконструирован по модульному принципу, управляется таблицами и запрограммирован на языке высокого уровня или - реализован с помощью компилятора компиляторов. - **Инкрементальный.** Повторно транслирует/компонует фрагменты программы и дополнения к ней без перекомпиляции всей программы. - **Интерпретирующий (пошаговый).** Последовательно выполняет независимую компиляцию каждого отдельного оператора (команды) исходной программы. - **Компилятор компиляторов.** Компилятор, воспринимающий формальное описание языка программирования и генерирующий компилятор для этого языка. - **Отладочный.** Устраняет отдельные виды синтаксических ошибок. - **Резидентный.** Постоянно находится в оперативной памяти и доступен для повторного использования многими задачами. - **Самокомпилируемый.** Написан на том же языке, с которого осуществляется компиляция. - **Универсальный.** Основан на формальном описании синтаксиса и семантики входного языка. Важными составными частями такого компилятора являются: ядро, синтаксический и семантический загрузчики. **Компиляция - это процесс преобразования программного кода из одного языка программирования в другой, как правило, с языка программирования высокого уровня в машинный код.** **Виды компиляции:** - **Пакетная.** Компиляция нескольких исходных модулей в одном задании. - **Построчная.** Машинный код порождается и затем исполняется для каждой завершённой грамматической конструкции языка. Внешне воспринимается как интерпретация, но имеет иное устройство. - **Условная.** На фазе трансляции результат трансляции зависит от условий, прописанных в исходном транслируемом тексте программы директивами компилятора. **История создания** Создание первых программ компиляции следует отнести к началу пятидесятых годов прошлого века. Главной задачей реализации первых компиляторов в то время было решение проблемы преобразования алгебраических выражений в машинные коды. А фактическим годом рождения теории компиляции может считаться 1957-ой год, когда была реализована первая программа компиляции языка Фортран, сформированная Джоном Бэкусом и выдававшая довольно эффективные объектные (машинные) коды. Этот компилятор был предназначен для платформ IBM 704, IBM 360 и DEC PDP-11. В восьмидесятом году прошлого века вышел новый вариант компилятора, предназначенный для IBM 360 и IBM РС, который поддерживал стандарт Fortran 77. Годом позже образовалась компания Watcom, представившая в 1988-ом году программу компиляции Си. Она мгновенно стала чрезвычайно популярной среди специалистов по программированию, поскольку могла генерировать наиболее быстрые коды в сравнении с другими компиляторами тех времён. **Джон Бэкус** ![Джон Бэкус](1.jpg) **Принцип работы** Компилятор – это системная программа, которая воспринимает на входе текст программы на языке высокого уровня (исходный модуль), а на выходе генерирует программу на языке ассемблера или машинном языке (объектный модуль). Объектный модуль состоит из двух основных частей: тела модуля, представляющего собой программу в кодах команд конкретной ЭВМ, и заголовка, содержащего внешние имена (имена переменных, используемых в данном модуле, но определённых в других модулях). Эта информация необходима для построения из набора объектных модулей программы или программной системы,готовой к выполнению. Объектные модули обрабатываются компоновщиком (редактором связей), который строит исполняемую программу (исполняемый файл, exe-модуль, загрузочный модуль) содержащую только команды ЭВМ. ![Компилятор](2.png) ![Принцип работы компилятора](3.png) Компиляция работает быстрее интерпретации, потому что компилятор запускается только один раз: делает перевод и отдает его процессору. Интерпретатор же запускается на каждой строке кода и нужен при каждом запуске программы. Кроме того, программный код в компиляторе уже переведен в машинный, поэтому требуется намного меньше времени для его исполнения. Поэтому, при разработке объёмных приложений лучше использовать компилятор. В то время как интерпретатор будет превосходить по скорости компилятор при использовании его в разработке небольших приложений. Отдельные программы компиляции, к примеру, Java, способны переводить программу не в машинные коды, а в программу на определённом специализированном языке низкого уровня. Данный язык, или по-другому байт-код, тоже может считаться языком машинных кодов, так как он должен интерпретироваться виртуальной машиной. К примеру, для языка Java языком виртуальной машины является JVM, или иначе байт-код Java. Для всех целевых машин, к примеру, IBM, Apple и так далее, и всех операционных систем или их семейств, используемых на целевой машине, необходимо написать свою программу компиляции. Есть ещё так называемые программы кросс-компиляции, которые позволяют на одной машине и одной операционной системе формировать коды, предназначенные для исполнения на другой целевой машине или другой операционной системе. Помимо этого, программы компиляции можно оптимизировать для разных типов процессоров из единого семейства. К примеру, коды, сформированные компилятором для процессоров семейства i686, могут применять специфические для данных процессоров инструкции ММХ, SSE, SSE2. Имеются также программы, решающие обратную задачу, а именно, они переводят программы с языка низкого уровня на язык высокого уровня. Такая процедура именуется декомпиляцией, а выполняющие её программы называются декомпиляторами. **Структура компилятора** Любой компилятор состоит из транслятора и компоновщика. Часто в качестве компоновщика компилятор использует внешний компоновщик, реализованный в виде самостоятельной программы, а сам выполняет лишь трансляцию исходного текста (по этой причине многие ошибочно считают компилятором разновидность транслятора). Компилятор может быть реализован и как своеобразная программа-менеджер, для трансляции программы вызывающая сооствествующий транслятор (трансляторы - если разные части программы написаны на разных языках программирования) и затем - для компоновки программы, - вызывающая компоновщик. Ярким примером такого компилятора является имеющаяся во всех UNIX-системах (и Linux-системах в том числе) утилита make (имеются реализации утилиты make и в других системах, в частности в Windows-системах). Процесс компиляции состоит из следующих фаз: 1. **Лексический анализ.** На этой фазе последовательность символов исходного файла преобразуется в последовательность лексем. 2. **Синтаксический (грамматический) анализ.** Последовательность лексем преобразуется в древо разбора. 3. **Семантический анализ.** Древо разбора обрабатывается с целью установления его семантики (смысла) — например, привязка идентификаторов к их определениям, типам данных, проверка совместимости типов данных, определение результирующих типов данных выражений и т. д. Результат обычно называется «промежуточным представлением/кодом», и может быть дополненным древом разбора, новым древом, абстрактным набором команд или чем-то ещё, удобным для дальнейшей обработки. 4. **Оптимизация.** Удаляются избыточные команды и упрощается (где это возможно) код с сохранением его смысла, т. е. реализуемого им алгоритма (в том числе предвычисляются (т. е. вычисляются на фазе трансляции) выражения, результаты которых практически являются константами). Оптимизация может быть на разных уровнях и этапах — например, над промежуточным кодом или над конечным машинным кодом. 5. **Генерация кода.** Из промежуточного представления порождается код на целевом языке (в том числе выполняется компоновка программы). **Примеры компиляторов** Для Windows: - Borland C++ Compiler - C++Builder XE7 - Dev-C++ - Microsoft Visual C++ Для Unix: - g++ - GNU Compiler Collection - Oracle Solaris Studio **Достоинства и недостатки** Достоинства компилятора: - Программный код уже переведен в машинный, следовательно, требуется меньше времени на его исполнение. - Файлы .exe выполняются быстрее, чем исходный код. Объектные программы сохраняются и могут быть запущены в любое время. - Объектные программы пользователю сложнее изменить, чем исходный код. - Компилятор проверяет исходный код на наличие синтаксических ошибок во время компиляции. Недостатки компиляторов: - Использует гораздо больше памяти компьютера. - При работе с компилятором невозможно изменить программу, не вернувшись к исходному коду. - Необходимо создавать объектную программу перед окончательным исполняемым файлом. Это может занять много времени. - Исходный код должен быть на 100% верным для создания исполняемого файла. **Декомпиляция** Существуют программы, которые решают обратную задачу - перевод программы с низкоуровневого языка на высокоуровневый. Этот процесс называют **декомпиляцией**, а такие программы - **декомпиляторами**. **Декомпилятор - это программа, транслирующая исполняемый модуль (полученный на выходе компилятора) в эквивалентный исходный код на языке программирования высокого уровня.** **Декомпиляция - процесс воссоздания исходного кода декомпилятором.** Декомпиляция, в частности, используется при обратной разработке программ. Удачность декомпиляции зависит от объема информации, представленной в декомпилируемом коде. Байт-код, используемый большинством виртуальных машин, часто содержит обширные метаданные, делающие декомпиляцию вполне выполнимой, в то время как машинный код более скуден и сложен в декомпиляции. В частности трудночитаемыми представляются вызовы подпрограмм или функций с косвенной адресацией вызовов. Если известно на каком языке была написана декомпилируемая программа, то в первую очередь дизассемблируются и анализируются библиотеки времени исполнения (RTL — runtime library) компилятора с этого языка, так как в основном компиляция программы сводится к вызовам с различными параметрами процедур из этих библиотек. Кроме того, многие компиляторы позволяют увидеть, в какой ассемблерный код превращаются операторы программы после компиляции. Эти конструкции становятся шаблонами для декомпилятора, поэтому процесс декомпиляции в некотором смысле похож на распознавание в машинном коде конечного набора подобных шаблонов. Легче всего распознаются вызовы процедур и возвраты из них. Они служат границами для восстановления операторов процедуры. Примеры декомпиляторов: - FernFlower - .NET Reflector, dotPeek — для декомпиляции сборок .NET - ILSpy - Delphi Decompiler - JAD — JAva Decompiler Для чего нужен декомпилятор: - взлом коммерческих программ и видеоигр. - исследование работы программы (реверс-инжиниринг). Например, есть мессенджер Skype. Протокол его взаимодействия с сервером не опубликован. А мы хотим создать свой мессенджер, который может работать в сети Skype. Или хотим сделать чит к игре. - поиск уязвимостей в программе, исходный код которой недоступен. - чтобы видеть не только ЧТО программа делает, но и КАК она это делает. _Таким образом, мы познакомились с такими понятиями, как: компилятор, компиляция, декомпилятор, декомпиляция. Узнали как работает компилятор и для чего нужен декомпилятор._ ## Список литературы [Декомпилятор](https://ru.wikipedia.org/wiki/Декомпилятор) [Компилятор](https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BC%D0%BF%D0%B8%D0%BB%D1%8F%D1%82%D0%BE%D1%80) [Компилятор против интерпертатора. Ключевые отличия](https://medium.com/nuances-of-programming/компилятор-vs-интерпретатор-ключевые-отличия-ef14a2aa0ee6) [Компиляторы: история создания и развития](https://spravochnick.ru/informacionnye_tehnologii/kompilyatory_istoriya_sozdaniya_i_razvitiya/) [Компиляция и интерпретация кода: что это такое и в чём разница](https://ru.hexlet.io/blog/posts/kompilyatsiya-i-interpretatsiya-koda-chto-eto-takoe-i-v-chem-raznitsa) [Принципы работы компилятора](https://studfile.net/preview/358641/page:6/) [Структура компиляторов. Общая схема работы компилятора](https://studfile.net/preview/2910570/)