Сайт о телевидении

Сайт о телевидении

» » Что такое компиляция программы. составные типы данных: массивы, файлы и др. Общие замечания к интерпретаторам

Что такое компиляция программы. составные типы данных: массивы, файлы и др. Общие замечания к интерпретаторам

Здравствуйте, дорогие читатели! Сегодня мы с вами немного окунемся в теорию. Наверняка, вы все когда-то хотели отправить свою супер-пупер программу другу. Но как это сделать? Не заставлять же его устанавливать PascalABC.NET! О том, как это сделать, мы сегодня и поговорим.

Все языки программирования делятся на два типа - интерпретируемые и компилируемые .

Интерпретаторы

Программируя на интерпретируемом языке, мы пишем программу не для выполнения в процессоре, а для выполнения программой-интерпретатором. Ее также называют виртуальной машиной.

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

При интерпретации выполнение кода происходит последовательно строка за строкой (от инструкции до инструкции). Операционная система взаимодействует с интерпретатором, а не исходным кодом.

Примеры интерпретируемых языков: PHP, JavaScript, C#, Python.

Скомпилированные программы работают быстрее, но при этом очень много времени тратится на компиляция исходного кода.

Программы же, рассчитанные на интерпретаторы, могут выполняться в любой системе, где таковой интерпретатор присутствует. Типичный пример - код JavaScript. Интерпретатором его выступает любой современный браузер. Вы можете однократно написать код на JavaScript, включив его в html-файл, и он будет одинаково выполняться в любой среде, где есть браузер. Не важно, будет ли это Safari в Mac OS, или же Internet Explorer в Windows.

Компиляторы

Компилятор - это программа, превращающая исходный текст, написанный на языке программирования, в машинные инструкции.

По мере преобразования текста программы в машинный код, компилятор может обнаруживать ошибки (синтаксиса языка, например). Поэтому все проблемы забытых точек с запятыми, забытых скобок, ошибок в названиях функций и переменных в данном случае решаются на этапе компиляции.

При компиляции весь исходный программный код (тот, который пишет программист) сразу переводится в машинный. Создается так называемый отдельный исполняемый файл , который никак не связан с исходным кодом. Выполнение исполняемого файла обеспечивается операционной системой. То есть образуется, например,.EXE файл.

Примеры компилируемых языков: C, C++, Pascal, Delphi.

Ход работы компилятора.

Препроцессинг

Эту операцию осуществляет текстовый препроцессор .

Исходный текст частично обрабатывается - производятся:

  • Замена комментариев пустыми строками
  • Подключение модулей и т. д. и т. п.

Компиляция

Результатом компиляции является объектный код .

Объектный код - это программа на языке машинных кодов с частичным сохранением символьной информации, необходимой в процессе сборки.

Компоновка

Компоновка также может носить следующие названия: связывание , сборка или линковка .

Это последний этап процесса получения исполняемого файла, состоящий из связывания воедино всех объектных файлов проекта .

EXE файл.

После компоновки у вас образуется.EXE файл вашей программы. Вы можете кинуть ее другу, и она откроется у него прямо в командной строке, как в старом добром DOS. Давайте попробуем создать.EXE файл. Все действия будут приводится в PascalABC.NET.

Заходим в Сервис -> Настройки -> Опции компиляции. Поверяем, стоит ли галочка напротив 2 пункта. Если стоит, то убираем ее.

Теперь откройте свою программу и запустите ее.

Откройте директорию, в которой у вас лежит исходный код программы.

Вот он,.EXE файл.

Кликаем по приложению. Как вы видите, после ввода данных, окошко сразу закрывается. Для того чтобы окно не закрывалось сразу, следует дописать две строчки кода, а именно: uses crt (перед разделом описания переменных) и readkey (в конце кода, перед оператором end).


Подключаем внешнюю библиотеку crt и используем встроенную в нее функцию readkey.

Теперь окно закроется по нажатию любой клавиши.

На заметку: PascalABC.NET - это интегрированная среда разработки.

Среда разработки включает в себя:

  • текстовый редактор;
  • компилятор;
  • средства автоматизации сборки;
  • отладчик.

На сегодня все! Задавайте любые вопросы в комментариях к этой статье. Не забывайте кликать по кнопочкам и делится ссылками на наш сайт со своими друзьями. А для того, чтобы не пропустить выход очередной статьи, рекомендую вам подписаться на рассылку новостей от нашего сайта. Одна из них находится в самом верху справа, другая - в футере сайта.

Номере "Компьютерных вестей" за этот год я рассказал вам о том, как устроен отладчик. Конечно, с тех пор прошло уже немало времени, но узнавать новое никогда не поздно. Сегодня мы с вами поговорим об устройстве ничуть не менее важного для программиста инструмента - компилятора.

Конечно, во многих ВУЗах есть специальные курсы, посвящённые устройству различных компонентов современных компиляторов и интерпретаторов. И современные компиляторы слишком сложны для того, чтобы рассказать о них в одной статье достаточно подробно. Тем не менее, базовые механизмы работы компиляторов остались неизменными со времён выпуска первого компилятора языка Фортран.


С высоты птичьего полёта...

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

Итак, что же это за части? Это лексический анализатор, или сканер; синтаксический анализатор, или парсер; семантический анализатор; а также один или несколько генераторов кода и один или несколько оптимизаторов. Также к компилятору часто относят дополнительные инструменты, нужные для создания исполняемого файла - сборщик и компоновщик.

Все эти названия для непосвящённого человека выглядят настоящей китайской грамотой. Однако, когда вы прочтёте о том, что делает каждый из компонентов компилятора, думаю, согласитесь, что концептуально это всё довольно просто.


От "А" до "Я"

Первый этап разбора исходного текста программы, осуществляемого компилятором, - это лексический анализ. Лексический анализатор считывает последовательно все слова (токены, лексемы) в тексте программы, преобразуя их в конструкции, которые затем уже используются для дальнейшего разбора текста. Делается это для того, чтобы различить в последующем различные идентификаторы и непосредственные конструкции самого языка (такие, как зарезервированные слова).

Следом за лексическим анализом может быть препроцессор. Тем, кто знаком с языками программирования C или С++, нет нужды объяснять, в чём состоит его функция. Для остальных же скажу, что основная задача препроцессора - это замена одних лексем другими, которые были заранее определены в тексте программы. Используется препроцессор также для условной компиляции (т.е. когда кусок кода должен быть откомпилирован только при выполнении определённых условий - для определённой платформы, только при отладочном билде и т.д. и т.п.), для выполнения определённых макросов (как в том же C/C++) и некоторых других подобных вещей. Препроцессор не является обязательной частью компилятора, поскольку многие языки программирования не нуждаются в нём.

Следующий этап - это синтаксический анализ, или парсинг. Этот этап компиляции выполняется синтаксическим анализатором, или парсером, и является, пожалуй, самым важным и, если можно так сказать, ответственным этапом компиляции. Компилятор рассматривает все токены, и, в зависимости от их значения и положения в тексте программы, формирует так называемое дерево разбора. То есть программа, бывшая до этого в недрах компилятора просто линейным набором символов, становится деревом, элементы которого расположены в соответствии с грамматикой того языка программирования, для которого написан данный конкретный компилятор.

Следом за синтаксическим анализом следует этап анализа семантического. Если синтаксический анализатор строил скелет нашей программы, то семантический помогает этому скелету обрасти плотью. Программа наполняется смыслом: переменные становятся переменными, объекты - объектами, а баги - багами. На самом деле, никакого волшебства не происходит - просто дерево разбора, терпеливо построенное парсером, дополняется семантической информацией о значении идентификаторов. Кстати, на этом этапе возникают и многие ошибки компиляции - например, такие, как несоответствие типов. Хотя, конечно, на парсинг тоже приходится изрядное количество ошибок, без которых, к сожалению, текст свеженаписанной программы обходится крайне редко даже у очень опытных программистов .

Дальше пути различных компиляторов расходятся. В большинстве компиляторов следом за этапом семантического анализа идёт перевод программы в некоторый промежуточный код, который может использоваться для генерации кода под разные аппаратные платформы. Если компилятор выполняет компиляцию только для какой-то одной аппаратной платформы, то программа может транслироваться в коды на языке Ассемблера соответствующей процессорной архитектуры, или, если компилятор трудится для какой-то виртуальной машины (как, например, в случае Java или Microsoft .NET), то переводиться программа может затем в специальный байт-код, понятный соответствующей виртуальной машине. Тем не менее, в большинстве современных компиляторов нет непосредственной трансляции в ассемблерный код - даже если в итоге компилятор не должен стараться для создания кросс-платформенных программ, всё равно, сначала идёт трансляция программы в какой-то промежуточный код, а только потом уже в исполняемый. Причина этого в оптимизации кода.

Современные компиляторы, даже самые слабенькие и плохонькие, поддерживают хотя бы базовую оптимизацию кода. Более мощные коммерческие компиляторы содержат в себе очень мощные алгоритмы оптимизации кода, которые позволяют при некоторых условиях сделать её в разы быстрее. Особенно мощными в плане оптимизации давным-давно тому назад считались компиляторы производства Watcom, сейчас, вроде бы, постепенно восстанавливающие свою былую славу в виде open-source продукта. Потом пальма первенства перешла к компиляторам Intel, и сейчас именно они считаются самыми лучшими компиляторами в плане оптимизации. Что ж, это довольно логично - кому, как ни создателям процессоров, знать, как лучше всего оптимизировать программы для работы на них. Впрочем, не важно, плоха оптимизация в компиляторе или нет - главное, что в любом оптимизирующем компиляторе есть модуль, называемый оптимизатором, который начинает свою работу после генератора промежуточного кода. Справедливости ради стоит сказать, что оптимизатор может работать и после генерации уже исполняемого кода, но в наши дни такая схема встречается уже редко, поскольку производители компиляторов, как правило, выпускают целую линейку подобных продуктов для разных языков программирования и стараются делать оптимизаторы, которые можно встроить в любой из этих компиляторов. Какими именно методами оптимизатор может повышать скорость работы программы - это тема отдельной статьи, которую, возможно, вы когда-нибудь и сможете увидеть на страницах "Компьютерных вестей".

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

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


Дополнительные компоненты

Как правило, компиляторы снабжаются, как я уже говорил выше, сборщиком и компоновщиком (ассемблером и линкером, как их называют чаще). Они помогают компилятору создать из исходного текста программы не просто ассемблерный код, а исполняемый файл, который программист может передать пользователю той операционной системы, для которой он писал программу, а тот уже сможет его запустить точно таким же образом, каким привык запускать все другие программы на своём компьютере.

Ассемблер и компоновщик в ряде случаев встроены прямо в компилятор, в других же случаях они выделяются в отдельные программы, которые запускаются после завершения работы самого компилятора. Их может и вовсе не быть, как, например, для компиляторов, преобразующих программы с одного языка высокого уровня на другой высокоуровневый язык (так называемых фронт-эндов), или они могут присутствовать только в виде, например, специфического сборщика, создающего код для виртуальной машины и помещающего его в какую-то специальную оболочку компоновщика (классический пример - Java с её JAR-файлами). Стоит, тем не менее, сказать пару слов о назначении этих двух инструментов.

Ассемблер (сборщик) - это программа, которая переводит код на языке Ассемблера в инструкции (операционные коды) процессора или в инструкции виртуальной машины. Поскольку язык Ассемблера - это низкоуровневый язык, то ассемблер не считают компилятором, хотя, конечно, он тоже производит некоторые этапы разбора программы, характерные для компилятора.

Компоновщик создаёт из того кода, который сгенерировал ассемблер, исполняемые файлы. Даже для одной и той же процессорной архитектуры исполняемые файлы будут отличаться в зависимости от операционной системы. Например, для Windows формат исполняемых файлов - это Portable Executable (PE), а для Linux - Executable Linked File (EXE).


Резюме

Как видите, если смотреть на компиляторы со стороны, то всё в них просто и не вызывает никаких особенно заковыристых вопросов. На практике всё, мягко говоря, немного сложнее. И если вы вдруг решите написать собственный компилятор, то не стоит заранее пугаться, хотя к определённым сложностям нужно, как и в любой новой работе, быть готовым. Я бы лично рекомендовал начинать знакомство с предметом с написания какого-нибудь простого эзотерического языка вроде Brainfuck или Whitespace. Поскольку сам я в своё время интересовался благодаря своему знакомому Марату Духану первым из них, то и вам рекомендую его.

Вообще, если же вы вдруг решили проникнуть глубже в тайны создания компиляторов, то в Интернете для вас найдётся масса литературы - и простой, и академически точной и подробной. Начать можно, например, отсюда: kit.kulichki.net . Хотя сайт уже не обновлялся целую вечность, информация, размещённая на нём, подойдёт для новичка и не устареет ещё не один десяток лет. Вообще, если погуглить, информации найдёте очень много, даже придётся её фильтровать. Так что успехов вам с компиляторами!

Вадим СТАНКЕВИЧ

Компьютеров, оснащённых векторным процессором .

  • Гибкий . Составлен по модульному принципу, управляется таблицами и запрограммирован на языке высокого уровня или реализован с помощью компилятора компиляторов.
  • Диалоговый . См.: диалоговый транслятор.
  • Инкрементальный . Повторно транслирует фрагменты программы и дополнения к ней без перекомпиляции всей программы.
  • Интерпретирующий (пошаговый) . Последовательно выполняет независимую компиляцию каждого отдельного оператора (команды) исходной программы.
  • Компилятор компиляторов . Транслятор, воспринимающий формальное описание языка программирования и генерирующий компилятор для этого языка.
  • Отладочный . Устраняет отдельные виды синтаксических ошибок.
  • Резидентный . Постоянно находится в основной памяти и доступен для повторного использования многими задачами.
  • Самокомпилируемый . Написан на том же языке, с которого осуществляется трансляция.
  • Универсальный . Основан на формальном описании синтаксиса и семантики входного языка. Составными частями такого компилятора являются: ядро, синтаксический и семантический загрузчики.
  • Виды компиляции

    • Пакетная . Компиляция нескольких исходных модулей в одном пункте задания.
    • Построчная . То же, что и интерпретация .
    • Условная . Компиляция, при которой транслируемый текст зависит от условий, заданных в исходной программе. Так, в зависимости от значения некоторой константы, можно включать или выключать трансляцию части текста программы.

    Основы

    Большинство компиляторов переводит программу с некоторого высокоуровневого языка программирования в машинный код , который может быть непосредственно выполнен центральным процессором . Как правило, этот код также ориентирован на исполнение в среде конкретной операционной системы , поскольку использует предоставляемые ею возможности (системные вызовы , библиотеки функций). Архитектура (набор программно-аппаратных средств), для которой производится компиляция, называется целевой машиной .

    Некоторые компиляторы (например, низкоуровневом языке. Такой язык - байт-код - также можно считать языком машинных команд, поскольку он подлежит интерпретации виртуальной машиной . Например, для языка Java это JVM (язык виртуальной машины Java), или так называемый байт-код Java (вслед за ним все промежуточные низкоуровневые языки стали называть байт-кодами). Для языков программирования на платформе .NET Framework ( , Managed C++, Visual Basic .NET и другие) - это MSIL (Microsoft Intermediate Language).

    Программа на байт-коде подлежит интерпретации виртуальной машиной , либо ещё одной компиляции уже в машинный код непосредственно перед исполнением. Последнее называется «Just-In-Time компиляция» (MSIL-код компилируется в код целевой машины также JIT-компилятором, а библиотеки .NET Framework компилируются заранее).

    Для каждой целевой машины (Apple и т. д.) и каждой операционной системы или семейства операционных систем, работающих на целевой машине, требуется написание своего компилятора. Существуют также так называемые кросс-компиляторы , позволяющие на одной машине и в среде одной ОС получать код, предназначенный для выполнения на другой целевой машине и/или в среде другой ОС. Кроме того, компиляторы могут быть оптимизированы под разные типы процессоров из одного семейства (путём использования специфичных для этих процессоров инструкций). Например, код, скомпилированный под процессоры семейства MMX, SSE2.

    Также существуют компиляторы, переводящие программу с языка высокого уровня на язык ассемблера .

    Существуют программы, которые решают обратную задачу - перевод программы с низкоуровневого языка на высокоуровневый. Этот процесс называют декомпиляцией, а программы - декомпиляторами . Но поскольку компиляция - это процесс с потерями, точно восстановить исходный код, скажем, на C++, в общем случае невозможно. Более эффективно декомпилируются программы в байт-кодах - например, существует довольно надёжный декомпилятор для Flash . Сходным процессом является дизассемблирование машинного кода в код на языке ассемблера, который всегда выполняется успешно. Связано это с тем, что между кодами машинных команд и командами ассемблера имеется практически однозначное соответствие.

    Структура компилятора

    Процесс компиляции состоит из следующих этапов:

    1. Лексический анализ . На этом этапе последовательность символов исходного файла преобразуется в последовательность лексем .
    2. Синтаксический (грамматический) анализ . Последовательность лексем преобразуется в дерево разбора.
    3. Семантический анализ. Дерево разбора обрабатывается с целью установления его семантики (смысла) - например, привязка идентификаторов к их декларациям, типам, проверка совместимости, определение типов выражений и т. д. Результат обычно называется «промежуточным представлением/кодом», и может быть дополненным деревом разбора, новым деревом, абстрактным набором команд или чем-то ещё, удобным для дальнейшей обработки.
    4. Оптимизация . Выполняется удаление излишних конструкций и упрощение кода с сохранением его смысла. Оптимизация может быть на разных уровнях и этапах - например, над промежуточным кодом или над конечным машинным кодом.
    5. Генерация кода . Из промежуточного представления порождается код на целевом языке.

    В конкретных реализациях компиляторов эти этапы могут быть раздельны или совмещены в том или ином виде.

    Трансляция и компоновка

    Важной исторической особенностью компилятора, отражённой в его названии (англ. compile - собирать вместе, составлять), являлось то, что он мог производить и компоновку (то есть содержал две части - транслятор и компоновщик). Это связано с тем, что раздельная компиляция и компоновка как отдельная стадия сборки выделились значительно позже появления компиляторов, и многие популярные компиляторы (например, GCC) до сих пор физически объединены со своими компоновщиками. В связи с этим, вместо термина «компилятор» иногда используют термин «транслятор» как его синоним : либо в старой литературе, либо когда хотят подчеркнуть его способность переводить программу в машинный код (и наоборот, используют термин «компилятор» для подчёркивания способности собирать из многих файлов один).

    Примечания

    См. также

    Реализации компиляторов
    • Sun Studio - компиляторы C, C++ и Fortran от Sun Microsystems Inc.
    • Open Watcom - свободное продолжение компиляторов Watcom C/C++/Fortran.
    • ICC AVR

    Литература

    • Альфред В. Ахо, Моника С. Лам, Рави Сети, Джеффри Д. Ульман. Компиляторы: принципы, технологии и инструментарий = Compilers: Principles, Techniques, and Tools. - 2-е изд. - М.: Вильямс , 2008. - ISBN 978-5-8459-1349-4
    • Робин Хантер. Основные концепции компиляторов = The Essence of Compilers. - М.: Вильямс , 2002. - С. 256. - ISBN 0-13-727835-7
    • Хантер Р. Проектирование и конструирование компиляторов / Пер. с англ. С. М. Круговой. - М.: Финансы и статистика, 1984. - 232 с.
    • Д. Креншоу. Давайте создадим компилятор! .

    Wikimedia Foundation . 2010 .

    Смотреть что такое "Компиляция (программирование)" в других словарях:

      Компиляция: В Викисловаре есть статья «компиляция» Компиляция (литература) (лат. … Википедия

      В информатике, препроцессор это компьютерная программа, принимающая данные на входе, и выдающая данные, предназначенные для входа другой программы, например, такой как компилятор. О данных на выходе препроцессора говорят, что они находятся в… … Википедия

      Эта статья во многом или полностью опирается на неавторитетные источники. Информация из таких источников не соответствует требованию проверяемости представленной информации, и такие ссылки не показывают значимость темы статьи. Статью можно… … Википедия

      Just in time compilation (JIT, компиляция «на лету»), dynamic translation (динамическая компиляция) технология увеличения производительности программных систем, использующих байт код, путём компиляции байт кода в машинный код… … Википедия

      Эту статью следует викифицировать. Пожалуйста, оформите её согласно правилам оформления статей. Условные обозначения … Википедия

      Python Класс языка: функциональный, объектно ориентированный, императивный, аспектно ориентированный Тип исполнения: интерпретация байт кода, компиляция в MSIL, компиляция в байт код Java Появился в: 1990 г … Википедия

      ГОСТ 19781-90: Обеспечение систем обработки информации программное. Термины и определения - Терминология ГОСТ 19781 90: Обеспечение систем обработки информации программное. Термины и определения оригинал документа: 9. Абсолютная программа Non relocatable program Программа на машинном языке, выполнение которой зависит от ее… … Словарь-справочник терминов нормативно-технической документации

    Виды компиляторов

    • Векторизующий . Транслирует исходный код в машинный код компьютеров, оснащённых векторным процессором .
    • Гибкий . Сконструирован по модульному принципу, управляется таблицами и запрограммирован на языке высокого уровня или реализован с помощью компилятора компиляторов.
    • Диалоговый . См.: диалоговый транслятор.
    • Инкрементальный . Повторно транслирует фрагменты программы и дополнения к ней без перекомпиляции всей программы.
    • Интерпретирующий (пошаговый) . Последовательно выполняет независимую компиляцию каждого отдельного оператора (команды) исходной программы.
    • Компилятор компиляторов . Транслятор, воспринимающий формальное описание языка программирования и генерирующий компилятор для этого языка.
    • Отладочный . Устраняет отдельные виды синтаксических ошибок.
    • Резидентный . Постоянно находится в оперативной памяти и доступен для повторного использования многими задачами.
    • Самокомпилируемый . Написан на том же языке, с которого осуществляется трансляция.
    • Универсальный . Основан на формальном описании синтаксиса и семантики входного языка. Составными частями такого компилятора являются: ядро, синтаксический и семантический загрузчики.

    Виды компиляции

    • Пакетная . Компиляция нескольких исходных модулей в одном пункте задания.
    • Построчная . То же, что и интерпретация .
    • Условная . Компиляция, при которой транслируемый текст зависит от условий, заданных в исходной программе директивами компилятора. Так, в зависимости от значения некоторой константы, можно включать или выключать трансляцию части текста программы.

    Структура компилятора

    Процесс компиляции состоит из следующих этапов:

    1. Лексический анализ . На этом этапе последовательность символов исходного файла преобразуется в последовательность лексем.
    2. Синтаксический (грамматический) анализ . Последовательность лексем преобразуется в дерево разбора.
    3. Семантический анализ. Дерево разбора обрабатывается с целью установления его семантики (смысла) - например, привязка идентификаторов к их декларациям, типам, проверка совместимости, определение типов выражений и т. д. Результат обычно называется «промежуточным представлением/кодом», и может быть дополненным деревом разбора, новым деревом, абстрактным набором команд или чем-то ещё, удобным для дальнейшей обработки.
    4. Оптимизация . Выполняется удаление излишних конструкций и упрощение кода с сохранением его смысла. Оптимизация может быть на разных уровнях и этапах - например, над промежуточным кодом или над конечным машинным кодом.
    5. Генерация кода . Из промежуточного представления порождается код на целевом языке.

    В конкретных реализациях компиляторов эти этапы могут быть разделены или, наоборот, совмещены в том или ином виде.

    Генерация кода

    Генерация машинного кода

    Большинство компиляторов переводит программу с некоторого высокоуровневого языка программирования в машинный код , который может быть непосредственно выполнен процессором . Как правило, этот код также ориентирован на исполнение в среде конкретной операционной системы , поскольку использует предоставляемые ею возможности (системные вызовы , библиотеки функций). Архитектура (набор программно-аппаратных средств), для которой производится компиляция, называется целевой машиной .

    Результат компиляции - исполнимый модуль - обладает максимальной возможной производительностью, однако привязан к определённой операционной системе и процессору (и не будет работать на других).

    Некоторые компиляторы переводят программу с языка высокого уровня не прямо в машинный код, а на язык ассемблера . Это делается для упрощения части компилятора, отвечающей за кодогенерацию, и повышения его переносимости (задача окончательной генерации кода и привязки его к требуемой целевой платформе перекладывается на ассемблер), либо для возможности контроля и исправления результата компиляции программистом.

    Генерация байт-кода

    Результатом работы компилятора может быть программа на специально созданном низкоуровневом языке , подлежащем интерпретации виртуальной машиной . Такой язык называется псевдокодом или байт-кодом . Как правило, он не является машинным кодом какого-либо компьютера и программы на нём могут исполняться на различных архитектурах, где имеется соответствующая виртуальная машина, но в некоторых случаях создаются аппаратные платформы, напрямую поддерживающие псевдокод какого-либо языка. Например, псевдокод языка Java называется байт-кодом Java и выполняется в Java Virtual Machine , для его прямого исполнения была создана спецификация процессора picoJava . Для платформы .NET Framework псевдокод называется Common Intermediate Language (CIL), а среда исполнения - Common Language Runtime (CLR).

    Некоторые реализации интерпретируемых языков высокого уровня (например, Perl) используют байт-код для оптимизации исполнения: затратные этапы синтаксического анализа и преобразование текста программы в байт-код выполняются один раз при загрузке, затем соответствующий код может многократно использоваться без промежуточных этапов.

    Динамическая компиляция

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

    CIL-код также компилируется в код целевой машины JIT-компилятором, а библиотеки .NET Framework компилируются заранее.

    Декомпиляция

    Существуют программы, которые решают обратную задачу - перевод программы с низкоуровневого языка на высокоуровневый. Этот процесс называют декомпиляцией, а такие программы - декомпиляторами . Но поскольку компиляция - это процесс с потерями, точно восстановить исходный код, скажем, на C++, в общем случае невозможно. Более эффективно декомпилируются программы в байт-кодах - например, существует довольно надёжный декомпилятор для Flash . Разновидностью декомпилирования является дизассемблирование машинного кода в код на языке ассемблера, который почти всегда выполняется успешно (при этом сложность может представлять самомодифицирующийся код или код, в котором собственно код и данные не разделены). Связано это с тем, что между кодами машинных команд и командами ассемблера имеется практически взаимно-однозначное соответствие.

    Раздельная компиляция

    Раздельная компиляция (англ. separate compilation ) - трансляция частей программы по отдельности с последующим объединением их компоновщиком в единый загрузочный модуль.

    Исторически особенностью компилятора, отражённой в его названии (англ. compile - собирать вместе, составлять), являлось то, что он производил как трансляцию , так и компоновку, при этом компилятор мог порождать сразу абсолютный код. Однако позже, с ростом сложности и размера программ (и увеличением времени, затрачиваемого на перекомпиляцию), возникла необходимость разделять программы на части и выделять библиотеки , которые можно компилировать независимо друг от друга. При трансляции каждой части программы компилятор порождает объектный модуль , содержащий дополнительную информацию, которая потом, при компоновке частей в исполнимый модуль, используется для связывания и разрешения ссылок между частями.

    Появление раздельной компиляции и выделение компоновки как отдельной стадии произошло значительно позже создания компиляторов. В связи с этим вместо термина «компилятор» иногда используют термин «транслятор» как его синоним: либо в старой литературе, либо когда хотят подчеркнуть его способность переводить программу в машинный код (и наоборот, используют термин «компилятор» для подчёркивания способности собирать из многих файлов один).

    На заре развития компьютеров первые компиляторы (трансляторы) называли «программирующими программами» (так как в тот момент программой считался только машинный код, а «программирующая программа» была способна из человеческого текста сделать машинный код, то есть запрограммировать ЭВМ).

    См. также

    Примечания

    Литература

    • Альфред В. Ахо, Моника С. Лам, Рави Сети, Джеффри Д. Ульман. Компиляторы: принципы, технологии и инструментарий = Compilers: Principles, Techniques, and Tools. - 2-е изд. - М .: Вильямс, 2010. - 1184 с. - ISBN 978-5-8459-1349-4
    • Робин Хантер. Основные концепции компиляторов = The Essence of Compilers. - М .: Вильямс, 2002. - 256 с. - ISBN 0-13-727835-7
    • Хантер Р. Проектирование и конструирование компиляторов / Пер. с англ. С. М. Круговой. - М .: Финансы и статистика, 1984. - 232 с.
    • Д. Креншоу. Давайте создадим компилятор!
    • Серебряков В. А., Галочкин М. П. Основы конструирования компиляторов .

    Wikimedia Foundation . 2010 .

    Синонимы :

    Смотреть что такое "Компилятор" в других словарях:

      - (ново лат., от лат. compilare грабить, обирать, выбирать). Составитель статей или книг путем заимствования отрывков из сочинений разных авторов. Словарь иностранных слов, вошедших в состав русского языка. Чудинов А.Н., 1910. КОМПИЛЯТОР… … Словарь иностранных слов русского языка

      См. писатель... Словарь русских синонимов и сходных по смыслу выражений. под. ред. Н. Абрамова, М.: Русские словари, 1999. компилятор автор, писатель; транслятор, халтурщик, программа Словарь русских синонимов … Словарь синонимов

      Программа, преобразующая текст, написанный на алгоритмическом языке, в программу, состоящую из машинных команд. Компилятор создает законченный вариант программы на машинном языке. См. также: Трансляторы Финансовый словарь Финам … Финансовый словарь

      КОМПИЛЯТОР, КОМПЬЮТЕРНАЯ ПРОГРАММА, которая переводит символы ЯЗЫКА ПРОГРАММИРОВАНИЯ в команды, которые может непосредственно воспринимать компьютер. Программы по большей части пишутся на ЯЗЫКАХ ВЫСОКОГО УРОВНЯ, таких как «Си», Паскаль или Бейсик … Научно-технический энциклопедический словарь

      КОМПИЛЯТОР, компилятора, муж. (книжн.). Автор компиляции. || Литератор, способный писать только компиляции (пренебр.). Жалкий компилятор. Толковый словарь Ушакова. Д.Н. Ушаков. 1935 1940 … Толковый словарь Ушакова

    Компьютеры сами по себе способны выполнять только очень ограниченный набор операций, называемых машинными кодами. В старые времена, когда появились первые компьютеры, программы писались в машинных кодах, представляющих собой последовательности двоичных чисел, однозначно воспринимаемых компьютером. В конце 50-х кодов прошлого века появились первые языки программирования, такие как язык ассемблера и Фортран. Для того, чтобы компьютер мог понять программу, написанную на каком-то языке программирования, необходим переводчик ( транслятор ) такой программы в машинные коды. Отметим, что, если оператор языка ассемблера отображается при трансляции чаще всего 1Некоторые операторы языка ассемблера, например, такие, как операторы ввода/вывода, отображаются в несколько машинных команд. в одну машинную инструкцию, предложения языков более высокого уровня отображаются, вообще говоря, в несколько машинных инструкций.

    Трансляторы бывают двух типов: компиляторы ( compiler ) и интерпретаторы ( interpreter ). Процесс компиляции состоит из двух частей: анализа ( analysis ) и синтеза ( synthesis ). Анализирующая часть компилятора разбивает исходную программу на составляющие ее элементы (конструкции языка) и создает промежуточное представление исходной программы. Синтезирующая часть из промежуточного представления создает новую программу, которую компьютер в состоянии понять. Такая программа называется объектной программой. Объектная программа может в дальнейшем выполняться без перетрансляции. В качестве промежуточного представления обычно используются деревья, в частности, так называемые деревья разбора. Под деревом разбора понимается дерево , каждый узел которого соответствует некоторой операции , а сыновья этого узла - операндам.

    Интерпретатор

    В отличие от компилятора, интерпретатор не создает никакой новой программы, а просто выполняет каждое предложение языка программирования. Можно сказать, что результатом работы интерпретатора является "число".

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

    В том случае, если исходный язык достаточно прост (например, если это язык ассемблера или Basic ), то никакое промежуточное представление не нужно, и тогда интерпретатор - это простой цикл . Он выбирает очередную инструкцию языка из входного потока, анализирует и выполняет ее. Затем выбирается следующая инструкция . Этот процесс продолжается до тех пор, пока не будут выполнены все инструкции, либо пока не встретится инструкция , означающая окончание процесса интерпретации.


    Компилятор


    Компилятор переводит программы с одного языка на другой. Входом компилятора служит цепочка символов , составляющая исходную программу на языке программирования . Выход компилятора (объектная программа ) также представляет собой цепочку символов, но принадлежащую другому языку , например, языку некоторого компьютера. При этом сам компилятор написан на языке , возможно, отличающемся от первых двух. Будем называть язык исходным языком, язык - целевым языком, а язык - языком реализации. Таким образом, можно говорить о компиляторе как об Pascal и кончая современными объектно-ориентированными языками такими, как C# и Java . Практически каждый язык программирования имеет какие-то особенности с точки зрения создателя транслятора. Однако мы начнем с рассмотрения разнообразных целевых языков компиляторов.