This project is a simple Virtual Machine (VM) designed to execute files written in P-Code-like intermediate code. The VM interprets p-code instructions and simulates the execution of the program, providing insights into the computation process of an abstract machine.
- Executes P-Code-like instructions in a simulated environment.
- Supports basic operations such as arithmetic, logic and function calls.
- Allows step-by-step execution for debugging and educational purposes.
- Provides a stack-based architecture similar to the p-code used in early compilers like Pascal.
- A valid P-Code-like file (intermediate code in the form of simple instructions).
-
Clone the repository:
git clone https://github.com/yourusername/p-code-vm.git cd p-code-vm -
Compile the C source code:
make
-
Run the Virtual Machine: Ensure you have a p-code file ready (e.g.,
program.pcode), and run the VM with the following command:./ program.txt
The virtual machine will interpret a p-code file and execute the corresponding instructions. The file should consist of a series of p-code operations, each corresponding to a specific instruction.
LOAD 5 // Load value 5 onto the stack
LOCI 5 // Load value onto the stack
ADDI // Add the two top value of the stack
STOR 1 // Store the result in variable 1
WRIT 1 // Output the value of variable 1
HALT // Stop execution
-
ADDI
Replaces the two integers onostackwith the result of their sum. -
ADDR
Replaces the two real numbers onostackwith the result of their sum. -
APOP
Popsastack(i.e., decrementsap--). -
CARD
Replaces the array on top ofostackwith its cardinality. -
CIDX
Checks whether the index on top ofostackis within the range[0..num], wherenumis the cardinality of the array below the top ofostack. If not, prints an error message and terminates program execution. -
CODE size
Allocatesprog(code memory) with a size ofsize(number of subsequent N-code instructions in the file). -
DIVI
Replaces the two integers onostackwith the result (integer) of their division. -
DIVR
Replaces the two real numbers onostackwith the result (real) of their division. -
EMPT
Replaces the array on top ofostackwith a boolean value (integer) indicating whether the array is empty. -
EQUA
Replaces the two objects onostackwith the boolean value (integer) resulting from the equality operation. -
FUNC fid
Instruction that is not executed: serves as a syntactic frame for function definition in the N-code program. -
GEQI
Replaces the two integers onostackwith the boolean value (integer) resulting from the≥comparison. -
GEQR
Replaces the two real numbers onostackwith the boolean value (integer) resulting from the≥comparison. -
GEQS
Replaces the two strings (pointers) onostackwith the boolean value (integer) resulting from the≥comparison. -
GTHI
Replaces the two integers onostackwith the boolean value (integer) resulting from the>comparison. -
GTHR
Replaces the two real numbers onostackwith the boolean value (integer) resulting from the>comparison. -
GTHS
Replaces the two strings (pointers) onostackwith the boolean value (integer) resulting from the>comparison. -
HALT
Stops the execution of the program. -
HEAD
Replaces the array on top ofostackwith its first element (head). If the array is empty, prints an error message and terminates execution. -
INDL offset size
Replaces the object on top ofostack(with anaddrfield) with an object whose value (of sizesize) is a copy of the value starting ataddr + offset. Setssize = sizeandnum = 1in the descriptor of the resulting object. -
IXAD scale
Pops an integer valueval(array index or field offset) fromostackand increments theaddrof the underlying object (now on top ofostack):addr += val * scale(thesizeandnumfields in the descriptor are not relevant). -
JUMP entry
Updates the program counter:pc = entry. -
LEQI
Replaces the two integers onostackwith the boolean value (integer) resulting from the≤comparison. -
LEQR
Replaces the two real numbers onostackwith the boolean value (integer) resulting from the≤comparison. -
LEQS
Replaces the two strings (pointers) onostackwith the boolean value (integer) resulting from the≤comparison. -
LOAD envoid
Loads ontoostackthe value of the object identified byoidin the environment (a variable ifenv = 0, a parameter ifenv = 1). -
LOCI intconst
Loads an integer with valueintconstontoostack. -
LOCR realconst
Loads a real number with valuerealconstontoostack. -
LOCS strconst
Loads ontoostacka pointer (unique for identical strings) to a string with valuestrconst. -
LODA env oid
Loads ontoostacka copy of the descriptor of the object identified byoidin the environment (a variable ifenv = 0, a parameter ifenv = 1): all fields of the descriptor copy (includingaddr) retain the same value. -
LTHI
Replaces the two integers onostackwith the boolean value (integer) resulting from the<comparison. -
LTHR
Replaces the two real numbers onostackwith the boolean value (integer) resulting from the<comparison. -
LTHS
Replaces the two strings (pointers) onostackwith the boolean value (integer) resulting from the<comparison. -
MEMB
Replaces the array on top ofostackand the element below it with a boolean value (integer) indicating whether the element belongs to the array. -
MULI
Replaces the two integers onostackwith the result of their multiplication. -
MULR
Replaces the two real numbers onostackwith the result of their multiplication. -
NEGB
Replaces the boolean value (integer) on top ofostackwith its negated value (0 becomes 1, and 1 becomes 0). -
NEGI
Replaces the integer numbernumon top ofostackwith-num(sign change). -
NEGR
Replaces the real numbernumon top ofostackwith-num(sign change). -
NEQU
Replaces the two objects onostackwith the boolean value (integer) resulting from the inequality operation. -
NEWO size num
Allocates an object invars[vp++]where:size = size,num = num. Ifnum > 0, allocates a byte string of lengthsize * numin the heap and assigns its pointer to theaddrfield of the descriptor; otherwise (ifnum = 0),addr = NULL. -
PACK num size card
Replacesnumobjects onostackwith a single object whose value (pointed to byaddr) is the concatenation of the values of the original objects (record fields or array elements), settingsize = sizeandnum = cardin the descriptor of the resulting object. -
PUSH n
Pushes a newRAontoastack, where:num = n,objs = op - n,ret = pc + 1. -
READ oid format
Assigns the value of variableoidby dynamically reading it from standard input in the givenformat. -
RETN
Replaces the current function's actual parameters (below the top ofostack) inastackwith the object on top ofostack; then updatespc = astack[ap - 1].ret. -
SKIP offset
Updatespc += offset - 1. -
SKPF offset
If the boolean value (integer) on top ofostackis0, updatespc += offset - 1; then, in any case, pops the boolean value (integer) from the top ofostack. -
STOR
Assigns the value at theaddrof the object below the top ofostackwith the value of the object on top ofostack; then pops both objects fromostack. If the size (num * size) of the value being assigned differs from that of the object below the top ofostack(in the case of an array), the old value (pointed to byaddr) is deallocated, and a new value is allocated with a number of bytes equal to the size of the value of the object on top ofostack. -
SUBI
Replaces the two integers onostackwith their difference. -
SUBR
Replaces the two real numbers onostackwith their difference. -
TAIL
Replaces the array on top ofostackwith its tail (all elements after the head). If the array is empty, prints an error message and terminates execution. -
TOIN
Replaces the real number on top ofostackwith the integer resulting from the cast operation. -
TORE
Replaces the integer on top ofostackwith the real number resulting from the cast operation. -
VARS num
Allocatesvars(global variable memory) with a size ofnum. -
WRIT format
Prints to standard output, in the givenformat, the instance of the object on top ofostack; then popsostack.
LODA 0 1 // load the address of variable with oid 1
LOAD 0 10 // Load 10 onto the stack
LOAD 0 20 // Load 20 onto the stack
ADDI // Add top two values (10 + 20)
STOR // Store result (30) in variable 1
LOAD 0 1 // Load variable 1 onto the stack
WRIT i // Print the value of integer variable 1 (30)
HALT // Stop execution
The program will output:
30- The VM reads the p-code file and parses each instruction.
- Each instruction is executed in a loop until the HALT instruction is encountered.
- The stack is used to store intermediate values and results.
- The VM provides feedback on the execution process, such as printing values when instructed.
Feel free to fork the repository, submit issues, or contribute improvements! Contributions are welcome, especially if you want to extend the instruction set or add new features to the VM.