на каком языке пишут компиляторы

Как компилятор может быть написан на том же языке который он компилирует?

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

1 ответ 1

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

С другими языками также такое происходило. К примеру, go был вначале написан на си, а потом код так модифицировали, что бы он был максимально похож на go код (https://go-review.googlesource.com/c/go/+/5652).

Но как появился самый первый компилятор тогда? Есть хорошая статья https://jameshfisher.com/2018/01/11/bootstrapping-a-c-compiler/ которая описывает, как поэтапно можно это сделать.

То есть, вначале все пишется ручками в памяти, в ноликах и единицах, потом постепенно наращиваются инструменты и в конце концов, такими итерациями можно дойти до современного мира. Вот люди пишут простейший си компилятор https://github.com/rdtscp/c-bootstrap

И будет ли трансляция в ассемблер по сути равна компиляции

если у нас есть компилятор ассемблера, то да. Почему «компилятор»? потому что ассемблеры бывают разные. Тот же FLAT assembler обладает таким разувесистым синтаксисом, что я бы побоялся его называть его компилятор «программой для замены на двоичный код».

Да, процесс, когда компилятор компилирует сам себя называется bootstrapping. и это не имеет отношения к html.

Источник

Кратчайшее введение в создание компилятора

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

Если первый опыт окажется успешным, то в будущем вас могут ожидать и другие 15-минутные «зарисовки» по тематике компиляторов.

О чем пойдет речь

Давайте сделаем компилятор арифметических выражений. Такой, который переведет исходный текст в обратной польской форме записи (ее еще называют RPN или ПОЛИЗ) в промежуточный код, работающий со стеком. Но мы обойдемся здесь без интерпретаторов. Далее мы сразу переведем результат в представление на языке Си. То есть у нас получится компилятор из RPN в Си.

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

Начнем с синтаксического анализа

Что мы здесь сделали? Функция scan получает от пользователя строку в обратной польской форме записи («2 2 +»).

А на выходе мы получаем ее промежуточное представление. Вот такое, например:

Вот так, мы уже получили компилятор. Но уж очень он несерьезный. Вспомним, что изначально речь шла о коде на Си.

Займемся трансляцией в Си

Что здесь происходит? Давайте посмотрим на вывод данной функции (на том же примере с «2 2 +»).

Да, это уже похоже на код на Си. Массив st играет роль стека, а sp — его указатель. Обычно с этими вещами работают виртуальные стековые машины.

Вот только самой машины — интерпретатора у нас-то и нет. Есть компилятор. Что нам осталось? Надо добавить необходимое обрамление для программы на Си.

Наш первый компилятор в готовом виде

Остается скомпилировать вывод данной программы компилятором Си.

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

Компилятор с использованием формы SSA

Вам нравится заголовок? SSA — это звучит очень солидно для любого компиляторщика. А мы уже сейчас будем использовать эту самую SSA. Что же это такое? Давайте двигаться по порядку.

Мы генерируем в данный момент код на Си, безо всяких виртуальных машин. Но зачем нам тогда рудимент в виде операций со стеком? Давайте заменим эти операции работой с обычными переменными из Си. Причем, мы не будем экономить переменные — для каждого выражения заведем новое имя. Пусть компилятор Си сам со всем этим разбирается. Получается, что у нас каждой переменной значение присваивается лишь однажды. А это, кстати говоря, и есть форма SSA.

Вот наш новый компилятор.

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

Вот окончательный результат:

Итоги

Похоже, время нашего совместного занятия истекло. Мы занимались тем, что переводили программу с одного языка на другой. Это называется source-to-source трансляцией. Или же — просто трансляцией, которую можно считать синонимом компиляции, но обычно компилятор переводит программу из высокоуровневого представления в низкоуровневое. Существует еще модное словечко «транспилятор» для обозначения source-to-source транслятора. Но упоминание «транспилятора» может вызвать раздражение у специалистов по компиляторам, будьте осторожны!

Источник

Как работает процессор и языки программирования

на каком языке пишут компиляторы. Смотреть фото на каком языке пишут компиляторы. Смотреть картинку на каком языке пишут компиляторы. Картинка про на каком языке пишут компиляторы. Фото на каком языке пишут компиляторы

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

Все описанное ниже как всегда упрощено для лучшего понимания.

Процессор и оперативная память

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

на каком языке пишут компиляторы. Смотреть фото на каком языке пишут компиляторы. Смотреть картинку на каком языке пишут компиляторы. Картинка про на каком языке пишут компиляторы. Фото на каком языке пишут компиляторы

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

Процессор знает много команд и у каждой из них есть свой числовой код, например:

на каком языке пишут компиляторы. Смотреть фото на каком языке пишут компиляторы. Смотреть картинку на каком языке пишут компиляторы. Картинка про на каком языке пишут компиляторы. Фото на каком языке пишут компиляторы

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

на каком языке пишут компиляторы. Смотреть фото на каком языке пишут компиляторы. Смотреть картинку на каком языке пишут компиляторы. Картинка про на каком языке пишут компиляторы. Фото на каком языке пишут компиляторы

Понимаете прикол? Это значит, что вам нужно писать код для каждой архитектуры процессора. Жуть.

Так. Понятно. Процессор может выполнять маленькие числовые команды. Но откуда он их берет? Из оперативной памяти. Думайте об оперативке, как о большом количестве маленьких ячеек. Каждая ячейка имеет свой адрес — это обычное число, например 2001. По адресу ячейки процессор может запросить данные и оперативная память вернет их ему. Также в эту ячейку процессор может записать новые данные.

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

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

на каком языке пишут компиляторы. Смотреть фото на каком языке пишут компиляторы. Смотреть картинку на каком языке пишут компиляторы. Картинка про на каком языке пишут компиляторы. Фото на каком языке пишут компиляторы

Ассемблер

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

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

на каком языке пишут компиляторы. Смотреть фото на каком языке пишут компиляторы. Смотреть картинку на каком языке пишут компиляторы. Картинка про на каком языке пишут компиляторы. Фото на каком языке пишут компиляторы

Согласитесь, что писать такой код очень сложно и легко запутаться. И это мы всего лишь написали код для решения простого уравнения. А теперь представьте, как написать ВКонтактик или Инстаграм.

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

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

Помните примеры кодов команд, которые были указаны выше? Теперь они выглядят так:

Также к названию команд были добавлены операнды (один или более), которые дают дополнительную информацию для выполнения команды.

на каком языке пишут компиляторы. Смотреть фото на каком языке пишут компиляторы. Смотреть картинку на каком языке пишут компиляторы. Картинка про на каком языке пишут компиляторы. Фото на каком языке пишут компиляторы

Рассмотрим еще один пример программы на ассемблере, которая выводит фразу «Hello, World!«. Пример ассемблированного кода:

Что-то слишком много непонятного кода для такой пустяковой задачи, не правда ли?

Языки программирования высшего уровня

Помните в самом начале я писал, что каждый производитель процессоров делает свою архитектуру? И что у каждой архитектуры свои числовые коды команд?

Так вот одну и ту же программу на ассемблере вам придется «пересобирать» под каждую из архитектур процессора. Для каждой архитектуры нужно скачивать отдельный инструмент Ассемблер и прогонять через него свой код.

Это усложняет портативность. Добавим сюда сложность в написании больших программ и получим необходимость в создании новых инструментов.

Так стали появляться языки программирования высокого уровня.

Их суть заключается в том, что цепочки команд на ассемблере были объединены в отдельные функции. Теперь вам достаточно написать одну команду, чтобы показать сообщение «Hello, World!».

Компилируемые языки

Первыми появились компилируемые языки программирования. К ним относится С, С++, Java и другие.

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

Рассмотрим чуть подробнее. Например на языке С вывод фразы «Hello, World!» будет выглядеть так: printf(«Hello, World!»). Просто и понятно.

на каком языке пишут компиляторы. Смотреть фото на каком языке пишут компиляторы. Смотреть картинку на каком языке пишут компиляторы. Картинка про на каком языке пишут компиляторы. Фото на каком языке пишут компиляторы

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

на каком языке пишут компиляторы. Смотреть фото на каком языке пишут компиляторы. Смотреть картинку на каком языке пишут компиляторы. Картинка про на каком языке пишут компиляторы. Фото на каком языке пишут компиляторы

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

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

на каком языке пишут компиляторы. Смотреть фото на каком языке пишут компиляторы. Смотреть картинку на каком языке пишут компиляторы. Картинка про на каком языке пишут компиляторы. Фото на каком языке пишут компиляторы

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

Интерпретируемые языки

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

Вот тут в ход идут интерпретируемые языки программирования такие как: Python, PHP, Perl, Pascal и другие.

Это тоже языки высшего порядка, которые также упрощают написание кода. Но у них есть как минимум два преимущества перед компилируемыми языками:

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

на каком языке пишут компиляторы. Смотреть фото на каком языке пишут компиляторы. Смотреть картинку на каком языке пишут компиляторы. Картинка про на каком языке пишут компиляторы. Фото на каком языке пишут компиляторы

Байткод — это код, который понимают все процессоры не зависимо от архитектуры.

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

Подытожим

Байткод — саааамый низкий язык, который понимает процессор.

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

Ассемблер — инструмент, который преобразует ассемблированный код в машинный. Программы на ассемблированном языке писать проще, чем машинный код, но все равно гемор.

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

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

Я надеюсь, что теперь вы лучше представляете, как работает ваш компьютер или смартфон и будете терпеливее относится к их затупам 🙂 Ведь железка не виновата, что тупит, а виноват горе-программист, который написал плохой код.

Если вы с чем-то не согласны, у вас есть вопросы или просто хотите сказать спасибо — прошу в комментарии. Пообщаемся 🙂

Источник

На чем пишут компиляторы? На C? Или, может, С++?

Если Вам нужен компилятор для языка X, чтобы получить компилятор для языка X (который написан на языке X), то как написать первый компилятор? Решение проблемы курицы и яйца возможно следующими методами:

1) Создать интерпретатор или компилятор для языка X на языке Y. Никлаус Вирт написал первый компилятор Паскаля на Фортране.
2) Этот интерпретатор или компилятор для полной версии языка X уже может быть написан на языке Y кем-то другим; такая раскрутка часто применяется для языка Scheme.
3) Первая версия компилятора может быть написана на подмножестве языка X, для которого уже существует некий другой компилятор; таким способом были раскручены некоторые подмножества Java, Haskell и Free Pascal.
4) Для создания компилятора языка X можно провести кросс-компиляцию на другой платформе, на которой уже существует компилятор для X; таким способом обычно портируются компиляторы, написанные на Си. Такой же способ используется для Free Pascal после начальной раскрутки.
5) Написание компилятора на языке X; затем компилирование вручную из исходного кода (вероятно всего, без оптимизации) и выполнение полученного кода для получения оптимизированного компилятора. Дональд Кнут использовал этот метод для своей системы грамотного программирования WEB.

есть старая добрая традиция: писать компилятор на том же самом языке.

Например, Си был изначально написан на Си, Си++ на первых шагах был написан на Си (но Си-же подмножество Си++, так что можете считать, что на Си++), дальше компиляторы писались на самом Си++ прошлого поколения.

В Юниксе исходник был на Си.

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

Источник

Что такое ассемблер и нужно ли его изучать

Этому языку уже за 70, но на пенсию он пока не собирается.

на каком языке пишут компиляторы. Смотреть фото на каком языке пишут компиляторы. Смотреть картинку на каком языке пишут компиляторы. Картинка про на каком языке пишут компиляторы. Фото на каком языке пишут компиляторы

на каком языке пишут компиляторы. Смотреть фото на каком языке пишут компиляторы. Смотреть картинку на каком языке пишут компиляторы. Картинка про на каком языке пишут компиляторы. Фото на каком языке пишут компиляторы

Есть традиция начинать изучение программирования с вывода на экран строки «Hello world!». На языке Python, например, это всего одна команда:

Всё просто, понятно и красиво! Но есть язык программирования, в котором, чтобы получить тот же результат, нужно написать солидный кусок кода:

Это ассемблер. Только не нужно думать, что он плох. Просто Python — это язык высокого уровня, а ассемблер — низкого. Одна команда Python при выполнении вызывает сразу несколько операций процессора, а каждая команда ассемблера — всего одну операцию.

Сложно? Давайте разбираться.

на каком языке пишут компиляторы. Смотреть фото на каком языке пишут компиляторы. Смотреть картинку на каком языке пишут компиляторы. Картинка про на каком языке пишут компиляторы. Фото на каком языке пишут компиляторы

Программист, консультант, специалист по документированию. Легко и доступно рассказывает о сложных вещах в программировании и дизайне.

Немного о процессорах и машинном языке

Чтобы объяснить, что такое язык ассемблера, начнём с того, как вообще работает процессор и на каком языке с ним можно «разговаривать».

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

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

Например, для Intel 8088 инструкция 0000001111000011B — это операция сложения двух чисел, а 0010101111000011B — вычитания.

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

Поэтому много лет назад был создан язык ассемблера, в котором коды операций обозначались буквами и сокращениями английских слов, отражающих суть команды. Например, команда mov ax, 6 означает: «переместить число 6 в ячейку памяти AX».

Когда и как был создан ассемблер?

Это произошло ещё в сороковых годах прошлого века. Ассемблер был создан для первых ЭВМ на электронных лампах, программы для которых писали на машинном языке. А так как памяти у компьютеров было мало, то команды вводили, переключая тумблеры и нажимая кнопки. Даже несложные вычисления занимали много времени.

Проблему решили, когда ЭВМ научились хранить программы в памяти. Уже в 1950 году была разработана первая программа-транслятор, которая переводила в машинный код программы, написанные на понятном человеку языке. Эту программу назвали программой-сборщиком, а язык — языком ассемблера (от англ. assembler — сборщик).

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

Как устроен язык ассемблера?

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

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

Регистрам и ячейкам памяти присваиваются символические имена, например:

EAX, EBX, AX, AH — имена для регистров;

meml — имя для ячейки памяти.

Например, так выглядит команда сложения чисел из регистров AX и BX:

А это команда вычитания чисел из регистров AX и BX:

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

Вот некоторые из них:

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

Вот, например, код, на ассемблере, выводящий на экран цифры от 1 до 10:

Здесь действие будет выполняться в цикле — как, например, в циклах for или do while в языках высокого уровня.

Единого стандарта для языков ассемблера нет. В работе с процессорами Intel разработчики придерживаются двух синтаксисов: Intel и AT&T. Ни у того ни у другого нет особых преимуществ: AT&T — стандартный синтаксис в Linux, а Intel используется в мире Microsoft.

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

Например, в синтаксисе Intel:

mov eax, ebx — команда перемещает данные из регистра eax в регистр ebx.

В синтаксисе AT&T эта команда выглядит так:

Почему для разных семейств процессоров нужен свой ассемблер?

Дело в том, что у каждого процессора есть набор характеристик — архитектура. Это его конструкция и принцип работы, а также регистры, адресация памяти и используемый набор команд. Если у процессоров одинаковая архитектура, то говорят, что они из одного семейства.

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

Кому и зачем нужен язык ассемблера?

Даже из нашего примера «Hello, World!» видно, что ассемблер не так удобен в разработке, как языки высокого уровня. Больших программ на этом языке сейчас никто не пишет, но есть области, где он незаменим:

Если вы хотите разрабатывать новые микропроцессоры или стать реверс-инженером, то есть смысл серьёзно заняться изучением языка ассемблера.

Востребованы ли программисты на ассемблере сегодня?

Конечно. Хотя на сайтах по поиску работу вы вряд ли найдёте заявки от работодателей с заголовками: «Нужен программист на ассемблере», зато там много таких, где требуется знание ассемблера дополнительно к языкам высокого уровня: C, C++ или Python. Это вакансии реверс-инженеров, специалистов по компьютерной безопасности, разработчиков драйверов и программ для микроконтроллеров/микропроцессоров, системных программистов и другие.

Предлагаемая зарплата — обычная в сфере IT: 80–300 тысяч рублей в зависимости от квалификации и опыта. Вот, например, вакансия реверс-инженера на HeadHunter, где требуется знание ассемблера:

на каком языке пишут компиляторы. Смотреть фото на каком языке пишут компиляторы. Смотреть картинку на каком языке пишут компиляторы. Картинка про на каком языке пишут компиляторы. Фото на каком языке пишут компиляторы

на каком языке пишут компиляторы. Смотреть фото на каком языке пишут компиляторы. Смотреть картинку на каком языке пишут компиляторы. Картинка про на каком языке пишут компиляторы. Фото на каком языке пишут компиляторы

на каком языке пишут компиляторы. Смотреть фото на каком языке пишут компиляторы. Смотреть картинку на каком языке пишут компиляторы. Картинка про на каком языке пишут компиляторы. Фото на каком языке пишут компиляторы

Стоит ли начинать изучение программирования с языка ассемблера?

Нет, так делать не нужно. Для этого есть несколько причин:

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

обложка: Полина Суворова для Skillbox Media

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *