P-code机 - 维基百科,自由的百科全书
在計算機科學中,P-code機(英語:P-code machine)是一種被設計來執行P-code的虛擬機器。P-code是一種被設計來運行在虛擬CPU上的匯編語言,即是我們現代所稱Bytecode的前身。P-code机这个词可用于形容所有这类机器(例如Java虚拟机和MATLAB预编译的代码),或者特指最有名的P-code机,來自於Pascal語言,特別是UCSD Pascal實作。
虽然這個概念在1966左右年就已首次实现(于BCPL的O-code与Euler语言的P - a code),[1]但P-code这个词直到70年代初才首次出现。 1973年Nori, Ammann, Jensen, Hageli和Jacobi编写的Pascal-P編譯器[2] 和1975年尼克劳斯·维尔特写的Pascal-S編譯器是早期的两个生成P-code的编译器。
P-code可以是一種與特定硬體平台無關的中間碼,一種虛擬機器碼。程式原始碼會先被轉換成P-code;轉換成P-code的程序,之後會由一個軟體來進行直譯。這個軟體可以模擬出一個假想的CPU來讀取p-code,之後將p-code轉換成實體機器碼來執行。但如果有足够的商业利益,可能可以實作做出该规格CPU的硬件实现(例如Pascal MicroEngine和Java处理器)。
UCSD p-Machine
[编辑]架构
[编辑]如很多其他p-code机一样,UCSD p-Machine是一个堆疊結構機器,这意味着大多数指令从堆栈中获取它们的操作数,并将结果放回堆栈上面。因此,“add”指令将堆栈最顶部的两个元素替换成它们的和。有几条指令就取一个参数。像Pascal一样,p-code是强类型语言,原生支持boolean (b), character (c), integer (i), real (r), set (s)和pointer (a)类型。
一些简单的指令:
Insn. Stack Stack Description before after adi i1 i2 i1+i2 add two integers adr r1 r2 r1+r2 add two reals dvi i1 i2 i1/i2 integer division inn i1 s1 b1 set membership; b1 = whether i1 is a member of s1 ldci i1 i1 load integer constant mov a1 a2 move not b1 ~b1 boolean negation
环境
[编辑]与其他基于堆栈的环境(如Forth和Java虚拟机)不同的是,p-系统非常类似于真正的目标CPU,它只有一个堆栈供过程栈帧(提过返回地址等)和局部指令参数共享。机器的其中三个寄存器指向这个堆栈(向上增加):
第五个寄存器 PC 指向当前指令的代码区。
调用约定
[编辑]栈帧是这样的:
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 指定嵌套级别的差异(记得Pascal支持过程嵌套)。这个指令会标记这个堆栈,即在上述栈帧中保留起始地5个格子,并初始化前面的 EP、动态链接和静态链接。
范例机器
[编辑]尼克劳斯·维尔特在他1976年出的书《算法+数据结构=程序》中详述了一个简单的P-code机。这个机器有3个寄存器——一个程序计数器 p,一个基寄存器 b,和一个栈顶寄存器 t。一共有8个指令,其中一个(opr)有多种形式。
这是机器的Pascal代码:
const levmax=3; amax=2047; type fct=(lit,opr,lod,sto,cal,int,jmp,jpc); instruction=packed record f:fct; l:0..levmax; a:0..amax; end; 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 = 1; writeln(' end pl/0'); end {interpret};
这个机器是用来运行维尔特的PL/0的,一个为教学开发的Pascal子集编译器。
注释
[编辑]- ^ Wirth, N.; Weber, H. EULER: a generalization of ALGOL, and its formal definition: Part II, Communications of the Association for Computing Machinery, Vol.9, No.2, pp.89-99. New York: ACM. 1966.[永久失效連結]
- ^ Nori, K.V.; Ammann, U.; Jensen, K.; Nageli, H. The Pascal P Compiler Implementation Notes. Zurich: Eidgen. Tech. Hochschule. 1975.
延伸阅读
[编辑]- Steven Pemberton and Martin Daniels: Pascal Implementation: The P4 Compiler and Interpreter(页面存档备份,存于互联网档案馆). ISBN 0-85312-358-6; ISBN 0-13-653031-1
- Steven Pemberton关于Pascal的网页(页面存档备份,存于互联网档案馆)上有P4编译器和解释器的Pascal源代码、使用说明和编译器的p-code (自身生成的)。
- The Jefferson Computer Museum's page on the UCSD p-System(页面存档备份,存于互联网档案馆)
- 开源实现(页面存档备份,存于互联网档案馆),包含打包和预编译的二进制文件;Klebsch的实现版本(页面存档备份,存于互联网档案馆)的一个友好的fork
- Compiling with C# and Java, Pat Terry, 2005, ISBN 0-321-26360-X, 624
- Algorithms + Data Structures = Programs, Niklaus Wirth, 1975, ISBN 0-13-022418-9
- Compiler Construction, Niklaus Wirth, 1996, ISBN 0-201-40353-6
- The Byte Book of Pascal, Blaise W. Liffick, Editor, 1979, ISBN 0-07-037823-1
- PASCAL - The Language and its Implementation, Edited by D.W. Barron, 1981, ISBN 0-471-27835-1. 尤其参见文章Pascal-P Implementation Notes和Pascal-S: A Subset and its Implementation.