<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh">
	<id>https://arolstar52-zhtest.hf.space/index.php?action=history&amp;feed=atom&amp;title=P-code%E6%9C%BA</id>
	<title>P-code机 - 版本历史</title>
	<link rel="self" type="application/atom+xml" href="https://arolstar52-zhtest.hf.space/index.php?action=history&amp;feed=atom&amp;title=P-code%E6%9C%BA"/>
	<link rel="alternate" type="text/html" href="https://arolstar52-zhtest.hf.space/index.php?title=P-code%E6%9C%BA&amp;action=history"/>
	<updated>2026-07-04T00:56:18Z</updated>
	<subtitle>在这个wiki上该页的修订历史</subtitle>
	<generator>MediaWiki 1.43.8</generator>
	<entry>
		<id>https://arolstar52-zhtest.hf.space/index.php?title=P-code%E6%9C%BA&amp;diff=2197053&amp;oldid=prev</id>
		<title>imported&gt;Willy1018-bot：​BOTR：批量替換所有lang-xx模板為langx模板( V6.4.0.1 )</title>
		<link rel="alternate" type="text/html" href="https://arolstar52-zhtest.hf.space/index.php?title=P-code%E6%9C%BA&amp;diff=2197053&amp;oldid=prev"/>
		<updated>2025-07-13T13:34:56Z</updated>

		<summary type="html">&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/%E6%9C%BA%E5%99%A8%E4%BA%BA/%E4%BD%9C%E4%B8%9A%E8%AF%B7%E6%B1%82#.E8.AB.8B.E6.B1.82.E6.89.B9.E9.87.8F.E6.9B.BF.E6.8F.9B.E6.89.80.E6.9C.89lang-xx.E6.A8.A1.E6.9D.BF.E7.82.BAlangx.E6.A8.A1.E6.9D.BF&quot; class=&quot;extiw&quot; title=&quot;wikipedia:机器人/作业请求&quot;&gt;BOTR&lt;/a&gt;：批量替換所有lang-xx模板為langx模板( V6.4.0.1 )&lt;/p&gt;
&lt;p&gt;&lt;b&gt;新页面&lt;/b&gt;&lt;/p&gt;&lt;div&gt;{{NoteTA&lt;br /&gt;
|G1 = IT&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
在[[計算機科學]]中，&amp;#039;&amp;#039;&amp;#039;P-code機&amp;#039;&amp;#039;&amp;#039;（{{langx|en|P-code machine}}）是一種被設計來執行P-code的[[虛擬機器]]。P-code是一種被設計來運行在虛擬[[CPU]]上的[[匯編語言]]，即是我們現代所稱[[Bytecode]]的前身。P-code机这个词可用于形容所有这类机器（例如[[Java虚拟机]]和[[MATLAB]]预编译的代码），或者特指最有名的P-code机，來自於[[Pascal (程式語言)|Pascal]]語言，特別是[[UCSD Pascal]]實作。&lt;br /&gt;
&lt;br /&gt;
虽然這個概念在1966左右年就已首次实现（于[[BCPL]]的O-code与Euler语言的P - a code），&amp;lt;ref&amp;gt;{{cite book |title=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 |url=http://dl.acm.org/citation.cfm?doid=365170.365202, |last1=Wirth |first1=N. |last2=Weber |first2=H. |publisher=ACM |location=New York |year=1966 }}{{Dead link|date=2020年3月 |bot=InternetArchiveBot |fix-attempted=yes }}&amp;lt;/ref&amp;gt;但P-code这个词直到70年代初才首次出现。&lt;br /&gt;
1973年Nori, Ammann, Jensen, Hageli和Jacobi编写的Pascal-P編譯器&amp;lt;ref&amp;gt;{{cite book &lt;br /&gt;
|title=The Pascal P Compiler Implementation Notes&lt;br /&gt;
|last1=Nori |first1=K.V. |last2=Ammann| first2=U. |last3=Jensen |first3=K. |last4=Nageli |first4=H.&lt;br /&gt;
|publisher=Eidgen. Tech. Hochschule |location=Zurich |year=1975 }}&amp;lt;/ref&amp;gt;&lt;br /&gt;
和1975年[[尼克劳斯·维尔特]]写的Pascal-S編譯器是早期的两个生成P-code的[[编译器]]。&lt;br /&gt;
&lt;br /&gt;
P-code可以是一種與特定硬體平台無關的[[中間語言|中間碼]]，一種虛擬[[機器碼]]。程式原始碼會先被轉換成P-code；轉換成P-code的程序，之後會由一個軟體來進行[[直譯器|直譯]]。這個軟體可以[[模擬器|模擬]]出一個假想的CPU來讀取p-code，之後將p-code轉換成實體機器碼來執行。但如果有足够的商业利益，可能可以實作做出该规格CPU的硬件实现（例如Pascal MicroEngine和Java处理器）。&lt;br /&gt;
&lt;br /&gt;
==UCSD p-Machine==&lt;br /&gt;
&lt;br /&gt;
===架构===&lt;br /&gt;
如很多其他p-code机一样，UCSD p-Machine是一个[[堆疊結構機器]]，这意味着大多数指令从堆栈中获取它们的操作数，并将结果放回堆栈上面。因此，“add”指令将堆栈最顶部的两个元素替换成它们的和。有几条指令就取一个参数。像Pascal一样，p-code是强类型语言，原生支持boolean (b), character (c), integer (i), real (r), set (s)和pointer (a)类型。&lt;br /&gt;
&lt;br /&gt;
一些简单的指令：&lt;br /&gt;
&lt;br /&gt;
 Insn.   Stack   Stack   Description&lt;br /&gt;
         before  after&lt;br /&gt;
 &amp;amp;nbsp;&lt;br /&gt;
 adi      i1 i2   i1+i2   add two integers&lt;br /&gt;
 adr      r1 r2   r1+r2   add two reals&lt;br /&gt;
 dvi      i1 i2   i1/i2   integer division&lt;br /&gt;
 inn      i1 s1   b1      set membership; b1 = whether i1 is a member of s1&lt;br /&gt;
 ldci     i1      i1      load integer constant&lt;br /&gt;
 mov      a1      a2      move&lt;br /&gt;
 not      b1      ~b1     boolean negation&lt;br /&gt;
&lt;br /&gt;
===环境===&lt;br /&gt;
与其他基于堆栈的环境（如[[Forth]]和[[Java虚拟机]]）不同的是，p-系统非常类似于真正的目标CPU，它只有一个堆栈供过程栈帧（提过[[返回地址]]等）和局部指令参数共享。机器的其中三个[[寄存器]]指向这个堆栈（向上增加）：&lt;br /&gt;
&lt;br /&gt;
* SP 指向堆栈顶部（[[堆栈指针]]）。&lt;br /&gt;
* MP 标记活动的栈帧的开始（[[标记指针]])。&lt;br /&gt;
* EP 指向当前过程的最高堆栈位置（[[极端指针]]）。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--Also present is a constant area, and, below that, the [[dynamic memory allocation|heap]] growing down towards the stack. The NP (the [[new pointer]]) register points to the top (lowest used address) of the heap. When EP gets greater than NP, the machine&amp;#039;s memory is exhausted.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
第五个寄存器 PC 指向当前指令的代码区。&lt;br /&gt;
&lt;br /&gt;
===调用约定===&lt;br /&gt;
栈帧是这样的：&lt;br /&gt;
&lt;br /&gt;
 EP -&amp;gt;&lt;br /&gt;
       local stack&lt;br /&gt;
 SP -&amp;gt; ...&lt;br /&gt;
       locals&lt;br /&gt;
       ...&lt;br /&gt;
       parameters&lt;br /&gt;
       ...&lt;br /&gt;
       return address (previous PC)&lt;br /&gt;
       previous EP&lt;br /&gt;
       dynamic link (previous MP)&lt;br /&gt;
       static link (MP of surrounding procedure)&lt;br /&gt;
 MP -&amp;gt; function return value&lt;br /&gt;
&lt;br /&gt;
程序调用序列的工作方式如下：下面指令引入调用&lt;br /&gt;
  mst n&lt;br /&gt;
其中 &amp;#039;&amp;#039;n&amp;#039;&amp;#039; 指定嵌套级别的差异（记得Pascal支持过程嵌套）。这个指令会&amp;#039;&amp;#039;标记&amp;#039;&amp;#039;这个堆栈，即在上述栈帧中保留起始地5个格子，并初始化前面的 EP、动态链接和静态链接。&amp;lt;!--The caller then computes and pushes any parameters for the procedure, and then issues&lt;br /&gt;
  cup n, p&lt;br /&gt;
to call a user procedure (&amp;#039;&amp;#039;n&amp;#039;&amp;#039; being the number of parameters, &amp;#039;&amp;#039;p&amp;#039;&amp;#039; the procedure&amp;#039;s address). This will save the PC in the return address cell, and set the procedure&amp;#039;s address as the new PC.&lt;br /&gt;
&lt;br /&gt;
User procedures begin with the two instructions&lt;br /&gt;
  ent 1, i&lt;br /&gt;
  ent 2, j&lt;br /&gt;
The first sets SP to MP + &amp;#039;&amp;#039;i&amp;#039;&amp;#039;, the second sets EP to SP + &amp;#039;&amp;#039;j&amp;#039;&amp;#039;. So &amp;#039;&amp;#039;i&amp;#039;&amp;#039; essentially specifies the space reserved for locals (plus the number of parameters plus 5), and &amp;#039;&amp;#039;j&amp;#039;&amp;#039; gives the number of entries needed locally for the stack. Memory exhaustion is checked at this point.&lt;br /&gt;
&lt;br /&gt;
Returning to the caller is accomplished via&lt;br /&gt;
  retC&lt;br /&gt;
with &amp;#039;&amp;#039;C&amp;#039;&amp;#039; giving the return type (i, r, c, b, a as above, and p for no return value). The return value has to be stored in the appropriate cell previously. On all types except p, returning will leave this value on the stack.&lt;br /&gt;
&lt;br /&gt;
Instead of calling a user procedure (cup), standard procedure &amp;#039;&amp;#039;q&amp;#039;&amp;#039; can be called with&lt;br /&gt;
  csp q&lt;br /&gt;
These standard procedures are Pascal procedures like &amp;#039;&amp;#039;readln()&amp;#039;&amp;#039; (&amp;quot;csp rln&amp;quot;), &amp;#039;&amp;#039;sin()&amp;#039;&amp;#039; (&amp;quot;csp sin&amp;quot;), etc. Peculiarly &amp;#039;&amp;#039;eof()&amp;#039;&amp;#039; is a p-Code instruction instead.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==范例机器==&lt;br /&gt;
尼克劳斯·维尔特在他1976年出的书《算法+数据结构=程序》中详述了一个简单的P-code机。这个机器有3个寄存器——一个[[程序计数器]] p，一个[[调用栈|基寄存器]] b，和一个[[堆栈|栈顶寄存器]] t。一共有8个指令，其中一个（opr）有多种形式。&lt;br /&gt;
&lt;br /&gt;
这是机器的Pascal代码：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
const&lt;br /&gt;
	levmax=3;&lt;br /&gt;
	amax=2047; &lt;br /&gt;
type &lt;br /&gt;
	fct=(lit,opr,lod,sto,cal,int,jmp,jpc);&lt;br /&gt;
	instruction=packed record &lt;br /&gt;
		f:fct;&lt;br /&gt;
		l:0..levmax;&lt;br /&gt;
		a:0..amax;&lt;br /&gt;
	end;&lt;br /&gt;
&lt;br /&gt;
procedure interpret;&lt;br /&gt;
&lt;br /&gt;
  const stacksize = 500;&lt;br /&gt;
&lt;br /&gt;
  var&lt;br /&gt;
    p, b, t: integer; {program-, base-, topstack-registers}&lt;br /&gt;
    i: instruction; {instruction register}&lt;br /&gt;
    s: array [1..stacksize] of integer; {datastore}&lt;br /&gt;
&lt;br /&gt;
  function base(l: integer): integer;&lt;br /&gt;
    var b1: integer;&lt;br /&gt;
  begin&lt;br /&gt;
    b1 := b; {find base l levels down}&lt;br /&gt;
    while l &amp;gt; 0 do begin&lt;br /&gt;
      b1 := s[b1];&lt;br /&gt;
      l := l - 1&lt;br /&gt;
    end;&lt;br /&gt;
    base := b1&lt;br /&gt;
  end {base};&lt;br /&gt;
&lt;br /&gt;
begin&lt;br /&gt;
  writeln(&amp;#039; start pl/0&amp;#039;);&lt;br /&gt;
  t := 0; b := 1; p := 0;&lt;br /&gt;
  s[1] := 0; s[2] := 0; s[3] := 0;&lt;br /&gt;
  repeat&lt;br /&gt;
    i := code[p]; p := p + 1;&lt;br /&gt;
    with i do&lt;br /&gt;
      case f of&lt;br /&gt;
        lit: begin t := t + 1; s[t] := a end;&lt;br /&gt;
        opr: &lt;br /&gt;
          case a of {operator}&lt;br /&gt;
            0: &lt;br /&gt;
              begin {return}&lt;br /&gt;
                t := b - 1; p := s[t + 3]; b := s[t + 2];&lt;br /&gt;
              end;&lt;br /&gt;
            1: s[t] := -s[t];&lt;br /&gt;
            2: begin t := t - 1; s[t] := s[t] + s[t + 1] end;&lt;br /&gt;
            3: begin t := t - 1; s[t] := s[t] - s[t + 1] end;&lt;br /&gt;
            4: begin t := t - 1; s[t] := s[t] * s[t + 1] end;&lt;br /&gt;
            5: begin t := t - 1; s[t] := s[t] div s[t + 1] end;&lt;br /&gt;
            6: s[t] := ord(odd(s[t]));&lt;br /&gt;
            8: begin t := t - 1; s[t] := ord(s[t] = s[t + 1]) end;&lt;br /&gt;
            9: begin t := t - 1; s[t] := ord(s[t] &amp;lt;&amp;gt; s[t + 1]) end;&lt;br /&gt;
            10: begin t := t - 1; s[t] := ord(s[t] &amp;lt; s[t + 1]) end;&lt;br /&gt;
            11: begin t := t - 1; s[t] := ord(s[t] &amp;gt;= s[t + 1]) end;&lt;br /&gt;
            12: begin t := t - 1; s[t] := ord(s[t] &amp;gt; s[t + 1]) end;&lt;br /&gt;
            13: begin t := t - 1; s[t] := ord(s[t] &amp;lt;= s[t + 1]) end;&lt;br /&gt;
          end;&lt;br /&gt;
        lod: begin t := t + 1; s[t] := s[base(l) + a] end;&lt;br /&gt;
        sto: begin s[base(l)+a] := s[t]; writeln(s[t]); t := t - 1 end;&lt;br /&gt;
        cal: &lt;br /&gt;
          begin {generate new block mark}&lt;br /&gt;
            s[t + 1] := base(l); s[t + 2] := b; s[t + 3] := p;&lt;br /&gt;
            b := t + 1; p := a&lt;br /&gt;
          end;&lt;br /&gt;
        int: t := t + a;&lt;br /&gt;
        jmp: p := a;&lt;br /&gt;
        jpc: begin if s[t] = 0 then p := a; t := t - 1 end&lt;br /&gt;
      end {with, case}&lt;br /&gt;
  until p = 1;&lt;br /&gt;
  writeln(&amp;#039; end pl/0&amp;#039;);&lt;br /&gt;
end {interpret};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
这个机器是用来运行维尔特的[[PL/0]]的，一个为教学开发的Pascal子集编译器。&lt;br /&gt;
&lt;br /&gt;
== 注释 ==&lt;br /&gt;
{{reflist}}&lt;br /&gt;
&lt;br /&gt;
== 延伸阅读 ==&lt;br /&gt;
* [[Steven Pemberton]] and Martin Daniels: [http://www.cwi.nl/~steven/pascal/book/ Pascal Implementation: The P4 Compiler and Interpreter]{{Wayback|url=http://www.cwi.nl/~steven/pascal/book/ |date=20170813152711 }}. ISBN 0-85312-358-6; ISBN 0-13-653031-1&lt;br /&gt;
*[http://homepages.cwi.nl/~steven/pascal/ Steven Pemberton关于Pascal的网页]{{Wayback|url=http://homepages.cwi.nl/~steven/pascal/ |date=20150219202544 }}上有P4编译器和解释器的Pascal源代码、使用说明和[https://web.archive.org/web/20020228000352/http://www.cwi.nl/ftp/pascal/pcom.code4.Z 编译器的p-code] （自身生成的）。&lt;br /&gt;
*[http://www.threedee.com/jcm/psystem/ The Jefferson Computer Museum&amp;#039;s page on the UCSD p-System]{{Wayback|url=http://www.threedee.com/jcm/psystem/ |date=20150217045428 }}&lt;br /&gt;
*[http://ucsd-psystem-vm.sourceforge.net/ 开源实现]{{Wayback|url=http://ucsd-psystem-vm.sourceforge.net/ |date=20140524054906 }}，包含打包和预编译的二进制文件；[http://www.klebsch.de Klebsch的实现版本]{{Wayback|url=http://www.klebsch.de/ |date=20200225210735 }}的一个友好的fork&lt;br /&gt;
* &amp;#039;&amp;#039;Compiling with C# and Java&amp;#039;&amp;#039;, Pat Terry, 2005, ISBN 0-321-26360-X, 624&lt;br /&gt;
* &amp;#039;&amp;#039;[[Algorithms + Data Structures = Programs]]&amp;#039;&amp;#039;, Niklaus Wirth, 1975, ISBN 0-13-022418-9&lt;br /&gt;
* &amp;#039;&amp;#039;Compiler Construction&amp;#039;&amp;#039;, Niklaus Wirth, 1996, ISBN 0-201-40353-6&lt;br /&gt;
* &amp;#039;&amp;#039;The Byte Book of Pascal&amp;#039;&amp;#039;, Blaise W. Liffick, Editor, 1979, ISBN 0-07-037823-1&lt;br /&gt;
* &amp;#039;&amp;#039;PASCAL - The Language and its Implementation&amp;#039;&amp;#039;, Edited by D.W. Barron, 1981, ISBN 0-471-27835-1.  尤其参见文章&amp;#039;&amp;#039;Pascal-P Implementation Notes&amp;#039;&amp;#039;和&amp;#039;&amp;#039;Pascal-S: A Subset and its Implementation&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
[[Category:Pascal]]&lt;br /&gt;
[[Category:编译器软件]]&lt;/div&gt;</summary>
		<author><name>imported&gt;Willy1018-bot</name></author>
	</entry>
</feed>