машина 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) типы данных .
Несколько простых инструкций:
Insn. Stack Stack Description before after adi i1 i2 i1+i2 add two integers adr r1 r2 r1+r2 add two reals inn i1 s1 b1 set membership; b1 = whether i1 is a member of s1 ldi i1 i1 i1 load integer constant mov a1 a2 a2 move not b1 b1 -b1 boolean negation
Среда
[ редактировать ]Подобно реальному целевому процессору, p-система имеет только один стек, общий для кадров стека процедур (обеспечивающий адрес возврата и т. д.) и аргументы для локальных инструкций. машины Три регистра указывают на стек (который растет вверх):
- SP указывает на вершину стека ( указатель стека ).
- MP отмечает начало активного кадра стека ( указатель метки ).
- EP указывает на самую верхнюю ячейку стека, используемую в текущей процедуре ( крайний указатель ).
Также присутствует постоянная область, а под ней — куча , растущая вниз к стопке. Регистр NP ( новый указатель ) указывает на вершину (наименьший используемый адрес) кучи. Когда EP становится больше, чем NP, память машины исчерпывается.
Пятый регистр PC указывает на текущую инструкцию в области кода.
Соглашения о вызовах
[ редактировать ]Этот раздел написан как руководство или руководство . ( январь 2024 г. ) |
Кадры стека выглядят следующим образом:
EP -> local stack SP -> ... locals ... parameters ... return address (previous PC) previous EP dynamic link (previous MP) static link (MP of surrounding procedure) MP -> function return value
Последовательность вызова процедуры работает следующим образом: Вызов начинается с
mst n
где n
определяет разницу в уровнях вложенности (помните, что Паскаль поддерживает вложенные процедуры). Эта инструкция пометит стек, т.е. зарезервирует первые пять ячеек вышеуказанного кадра стека и инициализирует предыдущую EP, динамическую и статическую ссылку. Затем вызывающая сторона вычисляет и передает любые параметры процедуры, а затем выдает
cup n, p
вызвать пользовательскую процедуру ( n
количество параметров, p
адрес процедуры). Это сохранит ПК в ячейке обратного адреса и установит адрес процедуры в качестве нового ПК.
Пользовательские процедуры начинаются с двух инструкций
ent 1, i ent 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]
Это код машины, написанный на языке Паскаль:
const
amax=2047; {maximum address}
levmax=3; {maximum depth of block nesting}
cxmax=200; {size of code array}
type
fct=(lit,opr,lod,sto,cal,int,jmp,jpc);
instruction=packed record
f:fct;
l:0..levmax;
a:0..amax;
end;
var
code: array [0..cxmax] of instruction;
procedure interpret;
const stacksize = 500;
var
p, b, t: integer; {program-, base-, topstack-registers}
i: instruction; {instruction register}
s: array [1..stacksize] of integer; {datastore}
function base(l: integer): integer;
var b1: integer;
begin
b1 := b; {find base l levels down}
while l > 0 do begin
b1 := s[b1];
l := l - 1
end;
base := b1
end {base};
begin
writeln(' start pl/0');
t := 0; b := 1; p := 0;
s[1] := 0; s[2] := 0; s[3] := 0;
repeat
i := code[p]; p := p + 1;
with i do
case f of
lit: begin t := t + 1; s[t] := a end;
opr:
case a of {operator}
0:
begin {return}
t := b - 1; p := s[t + 3]; b := s[t + 2];
end;
1: s[t] := -s[t];
2: begin t := t - 1; s[t] := s[t] + s[t + 1] end;
3: begin t := t - 1; s[t] := s[t] - s[t + 1] end;
4: begin t := t - 1; s[t] := s[t] * s[t + 1] end;
5: begin t := t - 1; s[t] := s[t] div s[t + 1] end;
6: s[t] := ord(odd(s[t]));
8: begin t := t - 1; s[t] := ord(s[t] = s[t + 1]) end;
9: begin t := t - 1; s[t] := ord(s[t] <> s[t + 1]) end;
10: begin t := t - 1; s[t] := ord(s[t] < s[t + 1]) end;
11: begin t := t - 1; s[t] := ord(s[t] >= s[t + 1]) end;
12: begin t := t - 1; s[t] := ord(s[t] > s[t + 1]) end;
13: begin t := t - 1; s[t] := ord(s[t] <= s[t + 1]) end;
end;
lod: begin t := t + 1; s[t] := s[base(l) + a] end;
sto: begin s[base(l)+a] := s[t]; writeln(s[t]); t := t - 1 end;
cal:
begin {generate new block mark}
s[t + 1] := base(l); s[t + 2] := b; s[t + 3] := p;
b := t + 1; p := a
end;
int: t := t + a;
jmp: p := a;
jpc: begin if s[t] = 0 then p := a; t := t - 1 end
end {with, case}
until p = 0;
writeln(' end pl/0');
end {interpret};
Эта машина использовалась для запуска 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 г.)