машина p-кода

редактировать

В компьютерном программировании, A р-машинный код ( портативный машинный код) представляет собой виртуальная машина предназначена для выполнения п-коды (на языке ассемблера или машинный код гипотетического центрального процессора (CPU)). Этот термин применяется как в целом ко всем таким машинам (таким как виртуальная машина Java (JVM) и предварительно скомпилированный код MATLAB ), так и к конкретным реализациям, наиболее известной из которых является p-Machine системы Pascal-P, в частности, UCSD Pascal. реализация, среди разработчиков которой p в p-коде толковалось как псевдокод чаще, чем переносимый, таким образом псевдокод означал инструкции для псевдо-машины.

Хотя концепция была впервые реализована примерно в 1966 году (как O-код для базового комбинированного языка программирования ( BCPL ) и P-код для языка Euler ), термин p-код впервые появился в начале 1970-х годов. Двумя ранними компиляторами, генерирующими p-код, были компилятор Pascal-P в 1973 году, созданный Кесавом В. Нори, Урсом Амманном, Кэтлин Йенсен, Ханс-Генрихом Нэгели и Кристианом Якоби, и компилятор Pascal-S в 1975 году Никлаусом Виртом.

Программы, которые были переведены в p-код, могут либо интерпретироваться программой, которая имитирует поведение гипотетического ЦП, либо транслироваться в машинный код ЦП, на котором программа должна запускаться и затем выполняться. Если есть достаточный коммерческий интерес, может быть построена аппаратная реализация спецификации ЦП (например, Pascal MicroEngine или версия процессора Java ).

СОДЕРЖАНИЕ
  • 1 Преимущества и недостатки внедрения p-кода
  • 2 UCSD p-машина
    • 2.1 Архитектура
    • 2.2 Окружающая среда
    • 2.3 Соглашения о вызовах
  • 3 Пример машины
  • 4 См. Также
  • 5 ссылки
  • 6 Дальнейшее чтение
Преимущества и недостатки внедрения p-кода

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

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

Одним из существенных недостатков p-кода является скорость выполнения, которую иногда можно исправить с помощью JIT-компиляции. P-код часто легче реконструировать, чем собственный код.

В начале 1980-х по крайней мере две операционные системы достигли машинной независимости благодаря широкому использованию p-кода. Операционная система Бизнес (BOS) была операционная система кросс-платформа, разработанная для запуска программ, р-код исключительно. UCSD р-система, разработанная в Университете Калифорнии, Сан - Диего, была самостоятельной компиляцией и самостоятельный хостингом операционной системой на основе р-кода, оптимизированную для генерации на Pascal языка.

В 1990-х годах перевод в p-код стал популярной стратегией для реализации таких языков, как Python, Microsoft P-Code в Visual Basic и байт-код Java в Java.

В языке Go используется универсальная переносимая сборка как форма p-кода, реализованная Кеном Томпсоном как расширение работы Bell Labs над Plan 9. В отличие от байт-кода Common Language Runtime (CLR) или байт-кода JVM, здесь нет стабильной спецификации, а инструменты сборки Go не генерируют формат байт-кода, который будет использоваться в более позднее время. Ассемблер Go использует общий язык ассемблера в качестве промежуточного представления, а исполняемые файлы Go - это машинно- зависимые статически связанные двоичные файлы.

UCSD p-машина

Архитектура

Как и многие другие машины с p-кодом, p-машина UCSD является стековой, что означает, что большинство инструкций берут свои операнды из стека и помещают результаты обратно в стек. Таким образом, addинструкция заменяет два самых верхних элемента стека их суммой. Несколько инструкций требуют немедленного аргумента. Как и Pascal, p-код строго типизирован и изначально поддерживает типы данных boolean (b), character (c), integer (i), real (r), set (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 is1  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

Среда

В отличие от других сред на основе стека (таких как Forth и виртуальная машина Java ), но очень похожих на реальный целевой ЦП, p-System имеет только один стек, совместно используемый кадрами стека процедур (с указанием адреса возврата и т. Д.), И аргументы для местные инструкции. Три машины регистров указывают в стек (который растет вверх):

  • SP указывает на вершину стека ( указатель стека ).
  • MP отмечает начало активного кадра стека ( указатель метки ).
  • EP указывает на место наивысшего стека, используемое в текущей процедуре ( крайний указатель ).

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

Пятый регистр, PC, указывает на текущую инструкцию в области кода.

Соглашения о вызовах

Фреймы стека выглядят так:

EP -gt; local stack SP -gt;... locals... parameters... return address (previous PC) previous EP dynamic link (previous MP) static link (MP of surrounding procedure) MP -gt; 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-кода.

Пример машины

Никлаус Вирт определил простую машину с p-кодом в книге 1976 года « Алгоритмы + структуры данных = программы». У машины было 3 регистра - счетчик программ p, базовый регистр b и регистр вершины стека t. Всего было 8 инструкций:

  1. горит 0, a  : постоянная нагрузки a
  2. opr 0, a  : выполнить операцию a (13 операций: RETURN, 5 математических функций и 7 функций сравнения)
  3. lod l, a  : переменная нагрузки l, a
  4. sto l, a  : сохранить переменную l, a
  5. cal l, a  : вызвать процедуру a на уровне l
  6. int 0, a  : увеличить t-регистр на a
  7. JMP 0,  : переход к а
  8. jpc 0, a  : условный переход к a

Это код машины, написанный на Паскале:

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 gt; 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] lt;gt; s[t + 1]) end; 10: begin t:= t - 1; s[t]:= ord(s[t] lt; s[t + 1]) end; 11: begin t:= t - 1; s[t]:= ord(s[t] gt;= s[t + 1]) end; 12: begin t:= t - 1; s[t]:= ord(s[t] gt; s[t + 1]) end; 13: begin t:= t - 1; s[t]:= ord(s[t] lt;= 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 Вирта, компилятора подмножества Паскаля, используемого для обучения разработке компиляторов.

Смотрите также
использованная литература
дальнейшее чтение
Последняя правка сделана 2023-04-05 06:54:49
Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
Обратная связь: support@alphapedia.ru
Соглашение
О проекте