Open main menu
Home
Random
Recent changes
Special pages
Community portal
Preferences
About Wikipedia
Disclaimers
Incubator escapee wiki
Search
User menu
Talk
Dark mode
Contributions
Create account
Log in
Editing
P-code machine
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
{{Short description|Programming virtual machine}} {{Use dmy dates|date=January 2020|cs1-dates=y}} In [[computer programming]], a '''P-code machine''' ('''portable code machine'''<ref>{{Cite book |last1=Upton |first1=Eben |last2=Duntemann |first2=Jeffrey |last3=Roberts |first3=Ralph |last4=Mamtora |first4=Tim |last5=Everard |first5=Ben |date=2016-09-13 |url=https://books.google.com/books?id=mU5ICgAAQBAJ&q=In+computer+programming%2C+a+p-code+machine%2C+or+portable+code+machine&pg=PA187 |title=Learning Computer Architecture with Raspberry Pi |publisher=John Wiley & Sons |isbn=978-1-119-18393-8 |language=en}}</ref>) is a [[virtual machine]] designed to execute ''P-code,'' the [[assembly language]] or [[machine code]] of a hypothetical [[central processing unit]] (CPU). The term ''P-code machine'' is applied generically to all such machines (such as the [[Java virtual machine]] (JVM) and [[MATLAB]] [[Bytecode|pre-compiled code]]), as well as specific implementations using those machines. One of the most notable uses of P-Code machines is the P-Machine of the [[Pascal-P]] system. The developers of the [[UCSD Pascal]] implementation within this system construed the ''P'' in ''P-code'' to mean ''pseudo'' more often than ''portable;'' they adopted a unique label for ''pseudo-code'' meaning instructions for a pseudo-machine. Although the concept was first implemented circa 1966 as [[BCPL#Design|O-code]] for the Basic Combined Programming Language ([[BCPL]]) and P code for the language [[Euler (programming language)|Euler]],<ref name="Wirth_1966"/> the ''term'' P-code first appeared in the early 1970s. Two early [[compiler]]s generating P-code were the Pascal-P compiler in 1973, by Kesav V. Nori, Urs Ammann, Kathleen Jensen, Hans-Heinrich Nägeli, and Christian Jacobi,<ref name="Nori_1975"/> and the [[Pascal-S]] compiler in 1975, by [[Niklaus Wirth]]. Programs that have been translated to P-code can either be [[Interpreter (computing)|interpreted]] by a software program that emulates the behaviour of the hypothetical CPU, or [[Binary translation|translated]] into the machine code of the CPU on which the program is to run and then executed. If there is sufficient commercial interest, a hardware implementation of the CPU specification may be built (e.g., the [[Pascal MicroEngine]] or a version of a [[Java processor]]). ==P-code versus machine code== While a typical [[compiler]] model is aimed at translating a program code into [[machine code]], the idea of a P-code machine follows a two-stage approach involving translation into P-code and execution by [[Interpreter (computing)|interpreting]] or [[just-in-time compilation]] (JIT) through the P-code machine. This separation makes it possible to detach the development of a P-code [[Interpreter (computing)|interpreter]] from the underlying machine code compiler, which has to consider machine-dependent behaviour in generating its [[bytecode]]. This way a P-code interpreter can also be implemented quicker, and the ability to interpret the code at runtime allows for additional [[Run-time checking|run-time checks]] which might not be similarly available in native code. Further, as P-code is based on an ideal virtual machine, a P-code program can often be smaller than the same program translated to machine code. Conversely, the two-step interpretation of a P-code-based program leads to a slower execution speed, though this can sometimes be addressed with [[just-in-time compilation]], and its simpler structure is easier to [[Reverse engineering|reverse-engineer]] than native code. ==Implementations of P-code== In the early 1980s, at least two [[operating system]]s achieved [[machine independence]] through extensive use of P-code {{Citation needed|date=October 2024}}. The [[Business Operating System (software)|Business Operating System]] (BOS) was a cross-platform [[operating system]] designed to run P-code programs exclusively. The [[UCSD p-System]], developed at The University of California, San Diego, was a self-compiling and [[Self-hosting (compilers)|self-hosting]] operating system based on P-code optimized for generation by the [[Pascal (programming language)|Pascal]] language. In the 1990s, translation into p-code became a popular strategy for implementations of languages such as [[Python (programming language)|Python]], [[Microsoft P-Code]] in [[Visual Basic]] and [[Java bytecode]] in [[Java (programming language)|Java]]. The language [[Go (programming language)|Go]] uses a generic, portable assembly as a form of p-code, implemented by [[Ken Thompson]] as an extension of the work on [[Plan 9 from Bell Labs]]. Unlike [[Common Language Runtime]] (CLR) bytecode or JVM bytecode, there is no stable specification and the Go build tools do not emit a bytecode format to be used at a later time. The Go assembler uses the generic assembly language as an [[intermediate representation]] and the Go executables are machine-specific [[statically linked]] binaries.<ref name="Pike_2016"/> ==UCSD P-Machine== ===Architecture=== Like many other P-code machines, the UCSD P-Machine is a [[stack machine]], which means that most instructions take their operands from a [[Stack (abstract data type)|stack]], and place results back on the stack. Thus, the <code>add</code> instruction replaces the two topmost elements of the stack with their sum. A few instructions take an immediate argument. Like Pascal, the P-code is [[Strong and weak typing|strongly typed]], supporting Boolean (b), character (c), integer (i), real (r), set (s), and pointer (a) [[data type]]s natively. Some simple instructions: 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 ===Environment=== Similar to a real target CPU, the P-System has only one stack shared by procedure stack frames (providing [[Return statement|return address]], etc.) and the arguments to local instructions. Three of the machine's [[Processor register|registers]] point into the stack (which grows upwards): * SP points to the top of the stack (the [[stack pointer]]). * MP marks the beginning of the active stack frame (the [[mark pointer]]). * EP points to the highest stack location used in the current procedure (the [[extreme pointer]]). 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's memory is exhausted. The fifth register, PC, points at the current instruction in the code area. ===Calling conventions=== {{how-to|section|date=January 2024}} Stack frames look like this: 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 The procedure calling sequence works as follows: The call is introduced with mst n where <code>n</code> specifies the difference in nesting levels (remember that Pascal supports nested procedures). This instruction will ''mark'' the stack, i.e. reserve the first five cells of the above stack frame, and initialize previous EP, dynamic, and static link. The caller then computes and pushes any parameters for the procedure, and then issues cup n, p to call a user procedure (<code>n</code> being the number of parameters, <code>p</code> the procedure's address). This will save the PC in the return address cell, and set the procedure's address as the new PC. User procedures begin with the two instructions ent 1, i ent 2, j The first sets SP to MP + <code>i</code>, the second sets EP to SP + <code>j</code>. So <code>i</code> essentially specifies the space reserved for locals (plus the number of parameters plus 5), and <code>j</code> gives the number of entries needed locally for the stack. Memory exhaustion is checked at this point. Returning to the caller is accomplished via retC with <code>C</code> 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. Instead of calling a user procedure (cup), standard procedure <code>q</code> can be called with csp q These standard procedures are Pascal procedures like <code>readln()</code> (<code>csp rln</code>), <code>sin()</code> (<code>csp sin</code>), etc. Peculiarly <code>eof()</code> is a p-Code instruction instead. ==Example machine== {{Textbook|section|date=January 2024}} [[Niklaus Wirth]] specified a simple p-code machine in the 1976 book ''[[Algorithms + Data Structures = Programs]]''. The machine had 3 registers - a [[program counter]] ''p'', a [[stack frame|base register]] ''b'' and a [[stack (data structure)|top-of-stack register]] ''t''. There were 8 instructions: # <code>'''lit''' 0, ''a''</code> : load constant {{mono|{{var|a}}}} # <code>'''opr''' 0, ''a''</code> : execute operation {{mono|{{var|a}}}} (13 operations: RETURN, 5 mathematical functions, and 7 comparison functions) # <code>'''lod''' ''l'', ''a''</code> : load variable {{mono|{{var|l}}}}, {{mono|{{var|a}}}} # <code>'''sto''' ''l'', ''a''</code> : store variable {{mono|{{var|l}}}}, {{mono|{{var|a}}}} # <code>'''cal''' ''l'', ''a''</code> : call procedure {{mono|{{var|a}}}} at level {{mono|{{var|l}}}} # <code>'''int''' 0, ''a''</code> : increment t-register by {{mono|{{var|a}}}} # <code>'''jmp''' 0, ''a''</code> : jump to {{mono|{{var|a}}}} # <code>'''jpc''' 0, ''a''</code> : jump conditional to {{mono|{{var|a}}}}<ref name="Hansotten"/> This is the code for the machine, written in Pascal: <syntaxhighlight lang="pascal"> 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}; </syntaxhighlight> This machine was used to run Wirth's [[PL/0]], a Pascal subset compiler used to teach compiler development.<ref>{{Cite report|last=Alpert|first=Donald|date=September 1979|title=A Pascal P-Code Interpreter for the Stanford Emmy|url=http://www.bitsavers.org/pdf/stanford/sel_techReports/TN164_A_Pascal_P-Code_Interpreter_for_the_Stanford_Emmy_Sep79.pdf|publisher=Computer Systems Laboratory, Departments of Eleotrioal Engineering and Computer Scienoes, Stanford University|id=Technioal Note No. 164}}</ref>{{Failed verification|date=April 2020}} ==Microsoft P-code== '''P-code''' is a name for several of [[Microsoft]]'s proprietary [[intermediate language]]s. They provided an alternate binary format to [[machine code]]. At various times, Microsoft has said P-code is an abbreviation for either ''packed code''<ref>{{cite web|url=http://msdn.microsoft.com/library/backgrnd/html/msdn_c7pcode2.htm|title=Microsoft P-Code Technology|first=Andy|last=Padawer|date=April 1992|website=[[Microsoft Developer Network]]|archive-url=https://web.archive.org/web/20010222035711/http://msdn.microsoft.com/library/backgrnd/html/msdn_c7pcode2.htm|archive-date=February 22, 2001}}</ref> or ''pseudo code''.<ref>{{cite web|url=http://msdn.microsoft.com/library/en-us/vbcon98/html/vbconcompilingyourprojecttonativecode.asp|title=Compiling Your Project to Native Code|date=2007|work=Visual Studio 6.0 Documentation|archive-url=https://web.archive.org/web/20070227000246/http://msdn.microsoft.com/library/en-us/vbcon98/html/vbconcompilingyourprojecttonativecode.asp|archive-date=February 27, 2007}}</ref> Microsoft P-code was used in [[Visual C++]] and [[Visual Basic (classic)|Visual Basic]]. Like other P-code implementations, Microsoft P-code enabled a more compact [[executable]] at the expense of slower execution. ==Other implementations== {{For|example implementations|Bytecode#Examples}} ==See also== {{Portal|Computer programming}} * [[Bytecode]] * [[Intermediate representation]] * [[Joel McCormack]], designer of the NCR Corporation version of the p-code machine * [[Runtime system]] * [[Token threading]] * [[City & Guilds Mnemonic Code]] * {{Annotated link|Platform-independent model}} ==References== {{Reflist|refs= <ref name="Wirth_1966">{{cite journal |last1=Wirth |first1=Niklaus |author-link1=Niklaus Wirth |last2=Weber |first2=Helmut |date=1966 |title=EULER: a generalization of ALGOL, and its formal definition: Part II |journal=[[Communications of the ACM]] |volume=9 |number=2 |pages=89–99 |doi=10.1145/365170.365202 |publisher=[[Association for Computing Machinery]] (ACM) |location=New York, USA |s2cid=12124100|doi-access=free }}</ref> <ref name="Nori_1975">{{cite book |last1=Nori |first1=Kesav V. |last2=Ammann |first2=Urs |last3=Jensen |first3=Kathleen |last4=Nägeli |first4= Hans-Heinrich |last5=Jacobi |first5=Christian |date=1975 |title=The Pascal P Compiler Implementation Notes |publisher=[[Eidgenössische Technische Hochschule]] (ETH) |location=Zürich, Switzerland}}</ref> <ref name="Pike_2016">{{cite web |title=The Design of the Go Assembler |last=Pike |first=Robert C. |website=[[YouTube]] |author-link=Robert C. Pike |type=Conference talk |date=2016 |access-date=2017-08-25 |url=https://www.youtube.com/watch?v=KINIAgRpkDA |archive-url=https://ghostarchive.org/varchive/youtube/20211211/KINIAgRpkDA| archive-date=2021-12-11 |url-status=live}}{{cbignore}}</ref> <ref name="Hansotten">{{cite web |title=Category Archives: Wirth - Euler - Designed by Niklaus Wirth and Helmut Weber |work=Pascal for small machines - Wirth languages, Pascal, UCSD, Turbo, Delphi, Freepascal, Oberon |date=2018-08-02 |url=http://pascal.hansotten.com/category/wirth/}}</ref> }} ==Further reading== * {{cite book |last1=Pemberton |first1=Steven |author-link1=Steven Pemberton |last2=Daniels |first2=Martin |title=Pascal Implementation: The P4 Compiler and Interpreter |url=http://www.cwi.nl/~steven/pascal/book/|publisher=[[John Wiley (publisher)|John Wiley]] |isbn=0-13-653031-1}} * {{cite web |editor-last=Pemberton |editor-first=Steven |editor-link=Steven Pemberton |url=http://homepages.cwi.nl/~steven/pascal/ |title=Pascal Implementation: A Book and Sources |date=2011-04-13}} (NB. Has Pascal sources of the [[Pascal-P4|P4]] compiler and interpreter, usage instructions.) * {{cite web |editor-last=Pemberton |editor-first=Steven |editor-link=Steven Pemberton |url=http://homepages.cwi.nl/~steven/pascal/pcom-code4.txt |title=pcode of the Pascal Compiler as compiled by itself |date=2011-04-13}} (NB. Has the P-code of the [[Pascal-P4|P4]] compiler, generated by itself.) * {{cite web |url=http://www.threedee.com/jcm/psystem/ |title=The Jefferson Computer Museum's page on the UCSD p-System}} * {{cite web |url=http://ucsd-psystem-vm.sourceforge.net/ |title=Open Source implementation}}, including packaging and pre-compiled binaries; a friendly fork of the {{cite web |url=http://www.klebsch.de |last=Klebsch |title=Klebsch implementation}} * {{cite book |title=Compiling with C# and Java |last=Terry |first=Pat |date=2005 |isbn=0-321-26360-X |page=624|publisher=Pearson/Addison-Wesley }} * {{cite book |last=Wirth |first=Niklaus |author-link=Niklaus Wirth |date=1975 |title=Algorithms + Data Structures = Programs |title-link=Algorithms + Data Structures = Programs |publisher=Prentice-Hall |isbn=0-13-022418-9}} * {{cite book |last=Wirth |first=Niklaus |author-link=Niklaus Wirth |date=1996 |title=Compiler Construction |publisher=Addison-Wesley |isbn=0-201-40353-6}} * {{cite book |editor-last=Liffick |editor-first=Blaise W. |date=1979 |title=The Byte Book of Pascal |publisher=BYTE Publications |isbn=0-07-037823-1}} * {{cite book |editor-last=Barron |editor-first=David William |editor-link=David William Barron |date=1981 |title=Pascal: The Language and its Implementation |publisher=Wiley |isbn=0-471-27835-1}} (NB. Especially see the articles ''Pascal-P Implementation Notes'' and ''Pascal-S: A Subset and its Implementation''.) ==External links== * {{webarchive|url=https://web.archive.org/web/20151222171103/http://www.woodmann.com/crackz/Tutorials/Vbpcode.htm|title=VB P-code Information by Mr Silver|date=December 22, 2015}} {{Authority control}} {{DEFAULTSORT:P-Code Machine}} [[Category:Stack-based virtual machines]] [[Category:Pascal (programming language)]] [[Category:Compilers|*]] [[Category:Programming language implementation]] [[Category:Articles with example Pascal code]]
Edit summary
(Briefly describe your changes)
By publishing changes, you agree to the
Terms of Use
, and you irrevocably agree to release your contribution under the
CC BY-SA 4.0 License
and the
GFDL
. You agree that a hyperlink or URL is sufficient attribution under the Creative Commons license.
Cancel
Editing help
(opens in new window)
Pages transcluded onto the current version of this page
(
help
)
:
Template:Annotated link
(
edit
)
Template:Authority control
(
edit
)
Template:Citation needed
(
edit
)
Template:Cite book
(
edit
)
Template:Cite report
(
edit
)
Template:Cite web
(
edit
)
Template:Failed verification
(
edit
)
Template:For
(
edit
)
Template:How-to
(
edit
)
Template:Mono
(
edit
)
Template:Portal
(
edit
)
Template:Reflist
(
edit
)
Template:Short description
(
edit
)
Template:Textbook
(
edit
)
Template:Use dmy dates
(
edit
)
Template:Webarchive
(
edit
)