WikiDer > P-кодовая машина
В компьютерное программирование, а машина p-кода, или же портативная кодовая машина[1] это виртуальная машина предназначен для выполнения p-код (в язык ассемблера гипотетического процессора). Этот термин применяется ко всем таким машинам (например, Виртуальная машина Java и MATLAB предварительно скомпилированный код), а также для конкретных реализаций, наиболее известной из которых является p-Machine Паскаль-П система, особенно UCSD Паскаль реализация (среди разработчиков которой «p» в «p-коде» толковалось как «псевдокод» чаще, чем «переносимый», «псевдокод», таким образом означая инструкции для псевдо-машины).
Хотя концепция была впервые реализована примерно в 1966 году (как О-код за BCPL и P - код для Язык Эйлера),[2] термин p-код впервые появился в начале 1970-х годов. Два ранних компиляторы генерирующий p-код был составлен компилятором Pascal-P в 1973 году Кесавом В. Нори, Урсом Амманном, Кэтлин Йенсен, Хансом-Генрихом Нэгели и Кристианом Якоби,[3] и Паскаль-S компилятор в 1975 г. Никлаус Вирт.
Программы, переведенные на p-код, могут быть интерпретированный с помощью программного обеспечения, которое имитирует поведение гипотетического ЦП, или переведено в машинный код ЦП, на котором должна выполняться программа, а затем выполняться. Если есть достаточный коммерческий интерес, может быть построена аппаратная реализация спецификации ЦП (например, Паскаль MicroEngine или версия Процессор Java).
Преимущества и недостатки внедрения p-кода
Этот раздел содержит формулировку, которая субъективно продвигает тему без передачи реальной информации. (Декабрь 2014 г.) (Узнайте, как и когда удалить этот шаблон сообщения) |
По сравнению с прямым переводом на родной Машинный код, двухэтапный подход, включающий перевод в p-код и выполнение устный переводчик или же своевременный компилятор дает несколько преимуществ.
- Гораздо проще написать небольшой интерпретатор p-кода для новой машины, чем модифицировать компилятор для генерации собственного кода для той же машины.
- Генерация машинного кода - одна из наиболее сложных частей написания компилятора. Для сравнения, генерация p-кода намного проще, потому что никакое машинно-зависимое поведение не должно учитываться при генерации байт-код. Это делает его полезным для быстрого запуска и запуска компилятора.
- Поскольку p-код основан на идеальной виртуальной машине, программа p-кода часто намного меньше, чем та же программа, переведенная в машинный код.
- Когда p-код интерпретируется, интерпретатор может применять дополнительные проверки во время выполнения которые сложно реализовать с помощью собственного кода.
Одним из существенных недостатков p-кода является скорость выполнения, которую иногда можно исправить с помощью JIT-компилятор. P-код часто также проще обратный инженер чем собственный код.
В начале 1980-х годов по крайней мере два операционные системы достигнуто машинная независимость благодаря широкому использованию p-кода. В Операционная система для бизнеса (BOS) была кроссплатформенной операционной системой, предназначенной исключительно для запуска программ с p-кодом. В UCSD p-система, разработанный в Калифорнийском университете в Сан-Диего, был самкомпилированным и самостоятельный[требуется разъяснение] операционная система на основе p-кода, оптимизированная для генерации Паскаль язык программирования.
В 1990-х годах перевод в p-код стал популярной стратегией для реализации таких языков, как Python, Microsoft P-код в Visual Basic и Байт-код Java в Ява.[4][неудачная проверка]
В Язык программирования Go использует универсальную переносимую сборку как форму p-кода, реализованную Кен Томпсон как продолжение работы над План 9 от Bell Labs. В отличие от CLR байт-код или байт-код JVM, стабильной спецификации нет, а инструменты сборки Go не генерируют формат байт-кода для использования в более позднее время. Ассемблер Go использует общий язык ассемблера как промежуточное представление, и исполняемые файлы Go зависят от машины статически связанный двоичные файлы.[5]
UCSD p-машина
Архитектура
Как и многие другие машины с p-кодом, p-машина UCSD является штабелеукладчик, что означает, что большинство инструкций берут свои операнды из стека и помещают результаты обратно в стек. Таким образом, команда «сложить» заменяет два самых верхних элемента стека их суммой. Несколько инструкций требуют немедленного аргумента. Как и Pascal, p-код строго типизирован, изначально поддерживает типы boolean (b), character (c), integer (i), real (r), set (s) и указатель (a).
Несколько простых инструкций:
Insn. Стек Описание стека до после adi i1 i2 i1 + i2 добавить два целых числа adr r1 r2 r1 + r2 добавить два вещественных числа dvi i1 i2 i1 / i2 целочисленное делениеinn i1 s1 b1 установить членство; b1 = является ли i1 членом s1ldci i1 i1 load integer constantmov a1 a2 movenot b1 ~ b1 логическое отрицание
Среда
В отличие от других сред на основе стека (например, Четвертый и Виртуальная машина Java), но очень похожий на реальный целевой ЦП, p-System имеет только один стек, совместно используемый кадрами стека процедур (обеспечивая обратный адреси т. д.) и аргументы в местные инструкции. Три машины регистры точка в стек (который растет вверх):
- SP указывает на вершину стека ( указатель стека).
- MP отмечает начало активного кадра стека ( отметка указатель).
- EP указывает на место наивысшего стека, используемое в текущей процедуре ( крайний указатель).
Также присутствует постоянная площадь, а под ней куча растет вниз к стеку. НП ( новый указатель) регистр указывает на верхнюю часть (наименьший используемый адрес) кучи. Когда EP становится больше NP, память машины исчерпана.
Пятый регистр, PC, указывает на текущую инструкцию в области кода.
Соглашения о вызовах
Фреймы стека выглядят так:
EP -> local stackSP -> ... locals ... parameters ... return address (предыдущий ПК) предыдущий EP динамическая ссылка (предыдущий MP) статическая ссылка (MP окружающей процедуры) MP -> возвращаемое значение функции
Последовательность вызова процедуры работает следующим образом: вызов вводится с помощью
mst n
куда п
определяет разницу в уровнях вложенности (помните, что Паскаль поддерживает вложенные процедуры). Эта инструкция будет отметка стек, то есть зарезервировать первые пять ячеек указанного выше кадра стека и инициализировать предыдущую EP, динамическую и статическую ссылку. Затем вызывающий абонент вычисляет и передает любые параметры процедуры, а затем выдает
чашка n, p
для вызова пользовательской процедуры (п
количество параметров, п
адрес процедуры). Это сохранит ПК в ячейке обратного адреса и установит адрес процедуры как новый ПК.
Пользовательские процедуры начинаются с двух инструкций
ent 1, i ent 2, j
Первый устанавливает SP в MP + я
, второй устанавливает EP в SP + j
. Так я
по существу определяет пространство, зарезервированное для местных жителей (плюс количество параметров плюс 5), и j
дает количество записей, необходимых локально для стека. На этом этапе проверяется нехватка памяти.
Возврат к звонящему осуществляется через
retC
с C
с указанием типа возврата (i, r, c, b, a, как указано выше, и p, если значение не возвращается). Возвращаемое значение должно быть предварительно сохранено в соответствующей ячейке. Для всех типов, кроме p, при возврате это значение останется в стеке.
Вместо вызова пользовательской процедуры (чашки) стандартная процедура q
можно назвать с
csp q
Эти стандартные процедуры являются процедурами Паскаля, например readln ()
(csp rln
), грех ()
(csp sin
) и т. д. eof ()
вместо этого является инструкцией p-кода.
Пример машины
Никлаус Вирт определил простую машину p-кода в книге 1976 года. Алгоритмы + Структуры данных = Программы. У машины было 3 регистра - a счетчик команд п, а базовый регистр б, а регистр вершины стека т. Всего было 8 инструкций:
- горит 0, а : постоянная нагрузки а
- опр 0, а : выполнить операцию а (13 операций: ВОЗВРАТ, 5 математических функций и 7 функций сравнения)
- дом л, а : загрузить переменную л, а
- сто л, а : хранить переменную л, а
- кал л, а : вызов процедуры а на уровне л
- int 0, а : увеличить t-регистр на а
- jmp 0, а : перейти к а
- jpc 0, а : переход по условию к а[6]
Это код машины, написанный на Паскале:
const Amax=2047; {максимальный адрес} levmax=3; {максимальная глубина вложения блоков} cxmax=200; {размер массива кода}тип fct=(горит,опр,дом,сто,кал,int,jmp,jpc); инструкция=упакованный записывать ж:fct; л:0..levmax; а:0..Amax; конец;вар код: множество [0..cxmax] из инструкция;процедура интерпретировать; const размер стека = 500; вар п, б, т: целое число; {программные, базовые, верхние регистры} я: инструкция; {регистр инструкций} s: множество [1..размер стека] из целое число; {хранилище данных} функция основание(л: целое число): целое число; вар b1: целое число; начинать b1 := б; {найти базовый уровень l ниже} пока л > 0 делать начинать b1 := s[b1]; л := л - 1 конец; основание := b1 конец {основание};начинать Writeln('start pl / 0'); т := 0; б := 1; п := 0; s[1] := 0; s[2] := 0; s[3] := 0; повторение я := код[п]; п := п + 1; с я делать дело ж из горит: начинать т := т + 1; s[т] := а конец; опр: дело а из {оператор} 0: начинать {возвращаться} т := б - 1; п := s[т + 3]; б := s[т + 2]; конец; 1: s[т] := -s[т]; 2: начинать т := т - 1; s[т] := s[т] + s[т + 1] конец; 3: начинать т := т - 1; s[т] := s[т] - s[т + 1] конец; 4: начинать т := т - 1; s[т] := s[т] * s[т + 1] конец; 5: начинать т := т - 1; s[т] := s[т] div s[т + 1] конец; 6: s[т] := ord(странный(s[т])); 8: начинать т := т - 1; s[т] := ord(s[т] = s[т + 1]) конец; 9: начинать т := т - 1; s[т] := ord(s[т] <> s[т + 1]) конец; 10: начинать т := т - 1; s[т] := ord(s[т] < s[т + 1]) конец; 11: начинать т := т - 1; s[т] := ord(s[т] >= s[т + 1]) конец; 12: начинать т := т - 1; s[т] := ord(s[т] > s[т + 1]) конец; 13: начинать т := т - 1; s[т] := ord(s[т] <= s[т + 1]) конец; конец; дом: начинать т := т + 1; s[т] := s[основание(л) + а] конец; сто: начинать s[основание(л)+а] := s[т]; Writeln(s[т]); т := т - 1 конец; кал: начинать {создать новую метку блока} s[т + 1] := основание(л); s[т + 2] := б; s[т + 3] := п; б := т + 1; п := а конец; int: т := т + а; jmp: п := а; jpc: начинать если s[т] = 0 тогда п := а; т := т - 1 конец конец {с, case} до того как п = 0; Writeln('конец пл / 0');конец {интерпретировать};
Эта машина использовалась для запуска вирта PL / 0, компилятор подмножества Паскаля, используемый для обучения разработке компиляторов.[7][неудачная проверка]
Смотрите также
- Яблоко Целое Сладкое 16
- Байт-код
- Джоэл МакКормак - разработчик версии машины p-кода корпорации NCR
- LLVM IR
- Microsoft P-код
- Система выполнения
- Распределение токенов
Рекомендации
- ^ Аптон, Эбен; Дантеманн, Джеффри; Робертс, Ральф; Мамтора, Тим; Эверард, Бен (13 сентября 2016). Изучение компьютерной архитектуры с Raspberry Pi. Джон Вили и сыновья. ISBN 978-1-119-18393-8.
- ^ Вирт, Никлаус; Вебер, Гельмут (1966). «EULER: обобщение АЛГОЛА и его формальное определение: Часть II». Коммуникации ACM. Нью-Йорк, США: Ассоциация вычислительной техники (ACM). 9 (2): 89–99. Дои:10.1145/365170.365202. S2CID 12124100.
- ^ Nori, Kesav V .; Амманн, Урс; Дженсен, Кэтлин; Нэгели, Ханс-Генрих; Якоби, Кристиан (1975). Замечания по реализации компилятора Pascal P. Цюрих, Швейцария: Eidgenössische Technische Hochschule (ETH).
- ^ «Система p-кода».
- ^ Пайк, Роберт С. (2016). «Дизайн Go Assembler» (Конференц-разговор). Получено 2017-08-25.
- ^ «Архив категорий: Вирт - Эйлер - Дизайн Никлауса Вирта и Гельмута Вебера». Паскаль для малых машин - языки вирт, Паскаль, UCSD, Turbo, Delphi, Freepascal, Oberon. 2018-08-02.
- ^ Альперт, Дональд (сентябрь 1979 г.). "Интерпретатор P-кода Pascal для Stanford Emmy" (PDF). Лаборатория компьютерных систем, факультеты элеотриальной инженерии и компьютерных наук, Стэнфордский университет. Техническая записка № 164. Цитировать журнал требует
| журнал =
(помощь)
дальнейшее чтение
- Пембертон, Стивен; Дэниелс, Мартин. Реализация Pascal: компилятор и интерпретатор P4. Эллис Хорвуд / Джон Вили. ISBN 0-13-653031-1.
- Пембертон, Стивен, изд. (2011-04-13). «Реализация Pascal: книга и исходники». (NB. Имеет исходники Pascal P4 компилятор и интерпретатор, инструкция по использованию.)
- Пембертон, Стивен, изд. (2011-04-13). «pcode компилятора Pascal, скомпилированный самим собой». (NB. Имеет p-код P4 компилятор, созданный самим собой.)
- "Страница компьютерного музея Джефферсона в системе UCSD p-System".
- «Реализация с открытым исходным кодом»., включая упаковку и предварительно скомпилированные двоичные файлы; дружеская вилка Klebsch. «Клебщая реализация».
- Терри, Пэт (2005). Компиляция с C # и Java. п. 624. ISBN 0-321-26360-X.
- Вирт, Никлаус (1975). Алгоритмы + Структуры данных = Программы. ISBN 0-13-022418-9.
- Вирт, Никлаус (1996). Конструкция компилятора. ISBN 0-201-40353-6.
- Liffick, Blaise W., ed. (1979). Байт-книга Паскаля. ISBN 0-07-037823-1.
- Бэррон, Дэвид Уильям, изд. (1981). PASCAL - Язык и его реализация. ISBN 0-471-27835-1. (NB. Особенно смотрите статьи Замечания по реализации Pascal-P и Паскаль-S: подмножество и его реализация.)