машина p-кода
В компьютерном программировании используется машина p-кода ( портативная кодовая машина). [1] ) — это виртуальная машина , предназначенная для выполнения p-кода ( языка ассемблера или машинного кода гипотетического центрального процессора (ЦП)). Этот термин применяется как в целом ко всем таким машинам (таким как виртуальная машина Java (JVM) и предварительно скомпилированный код MATLAB ), так и к конкретным реализациям, наиболее известной из которых является p-машина системы Pascal-P , особенно Реализация UCSD Pascal , среди разработчиков которой буква p в p-коде истолковывалась как псевдокод чаще , чем портативный , таким образом, псевдокод означал инструкции для псевдомашины.
Хотя концепция была впервые реализована примерно в 1966 году как O-код для базового комбинированного языка программирования ( BCPL ) и P-код для языка Эйлера , [2] термин p -код впервые появился в начале 1970-х годов. Двумя ранними компиляторами , генерирующими p-код, были компилятор Pascal-P 1973 года, созданный Кесавом В. Нори, Урсом Амманном, Кэтлин Йенсен, Хансом-Генрихом Нэгели и Кристианом Якоби. [3] и компилятор Pascal-S в 1975 году, созданный Никлаусом Виртом .
Программы, переведенные в p-код, могут либо интерпретироваться программой, которая имитирует поведение гипотетического ЦП, либо транслироваться в машинный код ЦП, на котором программа должна запускаться, а затем выполняться. Если существует достаточный коммерческий интерес, может быть создана аппаратная реализация спецификации ЦП (например, Pascal MicroEngine или версия процессора Java ).
внедрения p- кода недостатки Преимущества и
![]() | В данной статье поднимается несколько вопросов. Пожалуйста, помогите улучшить его или обсудите эти проблемы на странице обсуждения . ( Узнайте, как и когда удалять эти шаблонные сообщения )
|
По сравнению с прямой трансляцией в собственный машинный код двухэтапный подход, включающий трансляцию в p-код и выполнение путем интерпретации или JIT- компиляции, дает несколько преимуществ.
- Гораздо проще написать небольшой интерпретатор p-кода для новой машины, чем модифицировать компилятор для генерации собственного кода для той же машины.
- Генерация машинного кода — одна из наиболее сложных частей написания компилятора. Для сравнения, генерация p-кода намного проще, поскольку при генерации байт-кода не нужно учитывать машинно-зависимое поведение . Это делает его полезным для быстрого запуска и запуска компилятора.
- Поскольку p-код основан на идеальной виртуальной машине, программа с p-кодом часто намного меньше той же программы, переведенной в машинный код.
- При интерпретации p-кода интерпретатор может применять дополнительные проверки во время выполнения , которые трудно реализовать с помощью машинного кода.
Одним из существенных недостатков p-кода является скорость выполнения, которую иногда можно исправить с помощью компиляции Just-in-time . P-код часто легче перепроектировать, чем собственный код.
Реализации p-кода [ править ]
![]() | Этот раздел содержит формулировки, которые продвигают тему в субъективной манере, не передавая реальной информации . ( январь 2024 г. ) |
В начале 1980-х годов по крайней мере две операционные системы достигли машинной независимости благодаря широкому использованию p-кода. Бизнес -операционная система (BOS) представляла собой кросс-платформенную операционную систему, предназначенную исключительно для запуска программ p-кода. UCSD p-System , разработанная в Калифорнийском университете в Сан-Диего, представляла собой самокомпилируемую и саморазмещающуюся [ нужны разъяснения ] операционную систему, основанную на p-коде, оптимизированном для генерации языком Паскаль .
В 1990-х годах перевод в p-код стал популярной стратегией реализации таких языков, как Python , Microsoft P-Code в Visual Basic и байт-код Java в Java .
В языке Go используется универсальная переносимая сборка как форма p-кода, реализованная Кеном Томпсоном как расширение работы над Plan 9 от Bell Labs . В отличие от байт-кода Common Language Runtime (CLR) или байт-кода JVM, здесь не существует стабильной спецификации, а инструменты сборки Go не создают формат байт-кода, который будет использоваться позже. Ассемблер Go использует общий язык ассемблера в качестве промежуточного представления , а исполняемые файлы Go представляют собой статически связанные двоичные файлы, специфичные для конкретной машины. [4]
UCSD p-Машина [ править ]
Архитектура [ править ]
Как и многие другие машины с p-кодом, UCSD p-Machine является стековой машиной , что означает, что большинство инструкций берут свои операнды из стека и помещают результаты обратно в стек. Таким образом add
Инструкция заменяет два верхних элемента стека их суммой. Несколько инструкций требуют немедленного аргумента. Как и в Паскале, p-код строго типизирован и изначально поддерживает логический (b), символьный (c), целочисленный (i), вещественный (r), наборный (s) и указательный (a) типы данных .
Несколько простых инструкций:
Инсн. Описание стека стека до после adi i1 i2 i1+i2 сложить два целых числа adr r1 r2 r1+r2 добавить два действительных числа inn i1 s1 b1 набор членства; b1 = является ли i1 членом s1 ldi i1 i1 i1 загрузить целочисленную константу переместить a1 a2 a2 переместить не b1 b1 -b1 логическое отрицание
Окружающая среда [ править ]
Подобно реальному целевому процессору, p-система имеет только один стек, общий для кадров стека процедур (обеспечивающий адрес возврата и т. д.) и аргументы для локальных инструкций. машины Три регистра указывают на стек (который растет вверх):
- SP указывает на вершину стека ( указатель стека ).
- MP отмечает начало активного кадра стека ( указатель метки ).
- EP указывает на самую верхнюю ячейку стека, используемую в текущей процедуре ( крайний указатель ).
Также присутствует постоянная область, а под ней — куча , растущая вниз к стопке. Регистр NP ( новый указатель ) указывает на вершину (наименьший используемый адрес) кучи. Когда EP становится больше, чем NP, память машины исчерпывается.
Пятый регистр PC указывает на текущую инструкцию в области кода.
Соглашения о вызовах [ править ]
![]() | Этот раздел написан как руководство или руководство . ( январь 2024 г. ) |
Кадры стека выглядят следующим образом:
ЕР -> локальный стек СП -> ... местные жители ... параметры ... обратный адрес (предыдущий ПК) предыдущий EP динамическая ссылка (предыдущий MP) статическая ссылка (MP окружающей процедуры) MP -> возвращаемое значение функции
Последовательность вызова процедуры работает следующим образом: Вызов начинается с
мст н
где n
определяет разницу в уровнях вложенности (помните, что Паскаль поддерживает вложенные процедуры). Эта инструкция пометит стек, т.е. зарезервирует первые пять ячеек вышеуказанного кадра стека и инициализирует предыдущую EP, динамическую и статическую ссылку. Затем вызывающая сторона вычисляет и передает любые параметры процедуры, а затем выдает
чашка н, п
вызвать пользовательскую процедуру ( n
количество параметров, p
адрес процедуры). Это сохранит ПК в ячейке обратного адреса и установит адрес процедуры в качестве нового ПК.
Пользовательские процедуры начинаются с двух инструкций
ент 1, я ент 2, j
Первый устанавливает SP в MP+ i
, второй устанавливает EP в SP + j
. Так i
по существу указывает пространство, зарезервированное для локальных пользователей (плюс количество параметров плюс 5), и j
дает количество записей, необходимых локально для стека. На этом этапе проверяется исчерпание памяти.
Возврат к вызывающему абоненту осуществляется через
retC
с C
задавая тип возвращаемого значения (i, r, c, b, a, как указано выше, и p для отсутствия возвращаемого значения). Возвращаемое значение должно быть предварительно сохранено в соответствующей ячейке. Для всех типов, кроме p, возврат оставит это значение в стеке.
Вместо вызова пользовательской процедуры (чашки) используется стандартная процедура q
можно вызвать с помощью
csp q
Этими стандартными процедурами являются процедуры Паскаля, такие как readln()
( csp rln
), sin()
( csp sin
) и т. д. Своеобразно eof()
вместо этого является инструкцией p-кода.
Пример машины [ править ]
![]() | Этот раздел читается как учебник . ( январь 2024 г. ) |
Никлаус Вирт описал простую машину с кодом p-кода в книге 1976 года «Алгоритмы + структуры данных = программы» . Машина имела 3 регистра — программный счетчик p , базовый регистр b и регистр вершины стека t . Было 8 инструкций:
lit 0, a
: постоянная нагрузка аopr 0, a
: выполнить операцию а (13 операций: ВОЗВРАТ, 5 математических функций и 7 функций сравнения)lod l, a
: загрузить переменную л , аsto l, a
: сохранить переменную л , аcal l, a
: процедура вызова на уровне лint 0, a
: увеличить t-регистр на аjmp 0, a
: перейти к аjpc 0, a
: переход по условию на а [5]
Это код машины, написанный на языке Паскаль:
константа
амакс = 2047 ; {максимальный адрес}
levmax = 3 ; {максимальная глубина вложенности блоков}
cxmax = 200 ; {размер кодового массива}
type
fct = ( lit , opr , lod , sto , Cal , int , jmp , jpc ) ;
инструкция = упакованная запись
f : fct ;
л : 0 .. левмакс ;
а : 0 .. амакс ;
конец ;
var
код : массив [ 0 .. cxmax ] инструкций ;
процедура интерпретации ;
константный размер стека = 500 ;
вар
п , б , т : целое число ; {программа-, базовый-, верхний стек-регистры}
i : инструкция ; {регистр инструкций}
s : массив [ 1 .. размер стека ] целого числа ; {datastore}
функция base ( l : целое число ) : целое число ;
вар b1 : целое число ;
начать
b1 := b ; {найти базовый уровень l вниз}
while l > 0 do Begin
b1 := s [ b1 ] ;
л := л - 1
конец ;
база := b1
конец {база} ;
начать
запись ( 'начать pl/0' ) ;
т := 0 ; б := 1 ; п := 0 ;
с [ 1 ] := 0 ; с [ 2 ] := 0 ; с [ 3 ] := 0 ;
повторить
я := код [ п ] ; р := р + 1 ;
с i do
case f oflit
: : begin t = t + 1 ; s [ т ] = конец ; :
opr :
случай a { operator}
0 :
Begin {return}
t := b - 1 ; п := s [ т + 3 ] ; б := s [ т + 2 ] ;
конец ;
1 : с [ т ] := - с [ т ] ;
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 [ t ] := ord ( нечетное ( s [ t ])) ;
8 : начало т := т - 1 ; s [ t ] := ord ( s [ t ] = s [ t + 1 ]) end ;
9 : начало т := т - 1 ; s [ t ] := ord ( s [ t ] <> s [ t + 1 ]) end ;
10 : начало т := т - 1 ; s [ t ] := ord ( s [ t ] < s [ t + 1 ]) end ;
11 : начало т := т - 1 ; s [ t ] := ord ( s [ t ] >= s [ t + 1 ]) end ;
12 : начало т := т - 1 ; s [ t ] := ord ( s [ t ] > s [ t + 1 ]) end ;
13 : начало т := т - 1 ; s [ t ] := ord ( s [ t ] <= s [ t + 1 ]) end ;
конец ;
lod : начало т := т + 1 ; s [ т ] := s [ база ( л ) + а ] конец ;
Сто : начало s [ основание ( l ) + a ] := s [ t ] ; writeln ( s [ t ]) ; т := т - 1 конец ;
Cal :
начать {сгенерировать новую метку блока}
s [ t + 1 ] := base ( l ) ; s [ т + 2 ] := б ; s [ т + 3 ] := п ;
б := т + 1 ; п = конец
; :
int : т := т + а ;
jmp : п := а ;
jpc : начать, если s [ t ] = 0 , то p := a ; t := t - 1 end
end {with, case}
до тех пор, пока p = 0 ;
writeln ( 'конец pl/0' ) ;
конец {интерпретировать} ;
Эта машина использовалась для запуска PL/0 Вирта , подмножества компилятора Паскаля, используемого для обучения разработке компиляторов. [6] [ не удалось пройти проверку ]
Microsoft P-код [ править ]
P-Code — это название нескольких Microsoft проприетарных промежуточных языков . Они предоставили альтернативный двоичный формат машинному коду . В разное время Microsoft заявляла, что p-code — это аббревиатура для упакованного кода. [7] или псевдокод . [8]
Microsoft p-code использовался в Visual C++ и Visual Basic . Как и другие реализации p-кода, p-code Microsoft позволил сделать исполняемый файл более компактным за счет более медленного выполнения.
Другие реализации [ править ]
См. также [ править ]
- Байт-код
- Промежуточное представительство
- Джоэл МакКормак , разработчик версии машины p-кода корпорации NCR.
- Система выполнения
- Поток токенов
- Мнемонический код города и гильдий
- Платформонезависимая модель – модель разработки программного обеспечения
Ссылки [ править ]
- ^ Аптон, Эбен; Дантеманн, Джеффри; Робертс, Ральф; Мамтора, Тим; Эверард, Бен (13 сентября 2016 г.). Изучение компьютерной архитектуры с помощью Raspberry Pi . Джон Уайли и сыновья. ISBN 978-1-119-18393-8 .
- ^ Вирт, Никлаус ; Вебер, Гельмут (1966). «ЭЙЛЕР: обобщение АЛГОЛА и его формальное определение: Часть II» . Коммуникации АКМ . 9 (2). Нью-Йорк, США: Ассоциация вычислительной техники (ACM): 89–99. дои : 10.1145/365170.365202 . S2CID 12124100 .
- ^ Нори, Кесав В.; Амманн, Урс; Дженсен, Кэтлин; Нэгели, Ганс-Генрих; Якоби, Кристиан (1975). Замечания по реализации компилятора Pascal P. Цюрих, Швейцария: Швейцарский федеральный технологический институт (ETH).
- ^ Пайк, Роберт С. (2016). «Проектирование ассемблера Go» . YouTube (выступление на конференции). Архивировано из оригинала 11 декабря 2021 г. Проверено 25 августа 2017 г.
- ^ «Архивы категорий: Вирт - Эйлер - Разработано Никлаусом Виртом и Гельмутом Вебером» . Паскаль для небольших машин — вирт-языки, Pascal, UCSD, Turbo, Delphi, Freepascal, Oberon . 2018-08-02.
- ^ Альперт, Дональд (сентябрь 1979 г.). Интерпретатор P-кода Паскаля для Стэнфордской премии «Эмми» (PDF) (Отчет). Лаборатория компьютерных систем, факультеты элеотриальной инженерии и компьютерных наук, Стэнфордский университет. Техническая нота № 164.
- ^ Падавер, Энди (апрель 1992 г.). «Технология Microsoft P-Code» . Сеть разработчиков Microsoft . Архивировано из оригинала 22 февраля 2001 г.
- ^ «Компиляция вашего проекта в нативный код» . Документация Visual Studio 6.0 . 2007. Архивировано из оригинала 27 февраля 2007 г.
Дальнейшее чтение [ править ]
- Пембертон, Стивен ; Дэниелс, Мартин. Реализация Паскаля: компилятор и интерпретатор P4 . Джон Уайли . ISBN 0-13-653031-1 .
- Пембертон, Стивен , изд. (13 апреля 2011 г.). «Реализация Паскаля: книга и источники» . (Примечание. Содержит исходные коды компилятора и интерпретатора P4 на языке Pascal , инструкции по использованию.)
- Пембертон, Стивен , изд. (13 апреля 2011 г.). «pcode компилятора Pascal, скомпилированный сам по себе» . (Примечание. Имеет p-код компилятора P4 , сгенерированный им самим.)
- «Страница Компьютерного музея Джефферсона о p-системе UCSD» .
- «Реализация с открытым исходным кодом» . , включая упаковку и предварительно скомпилированные двоичные файлы; дружеская вилка Клебш. «Реализация Клебша» .
- Терри, Пэт (2005). Компиляция с помощью C# и Java . Пирсон/Аддисон-Уэсли. п. 624. ИСБН 0-321-26360-Х .
- Вирт, Никлаус (1975). Алгоритмы + Структуры данных = Программы . Прентис-Холл. ISBN 0-13-022418-9 .
- Вирт, Никлаус (1996). Конструкция компилятора . Аддисон-Уэсли. ISBN 0-201-40353-6 .
- Лиффик, Блез В., изд. (1979). Байтовая книга Паскаля . Публикации БАЙТА. ISBN 0-07-037823-1 .
- Бэррон, Дэвид Уильям , изд. (1981). Паскаль: Язык и его реализация . Уайли. ISBN 0-471-27835-1 . (Примечание. В частности, см. статьи « Замечания по реализации Pascal-P» и «Pascal-S: подмножество и его реализация ».)
Внешние ссылки [ править ]
- Информация о P-коде VB, предоставленная г-ном Сильвером на Wayback Machine (архивировано 22 декабря 2015 г.)