project: Simple JS stack machine

Details

Simulation of a minimalistic stack machine, written in javascript.

  • last updated: July, 2018
Download source

Source explorer

README.md

View raw
# Simple JS stack machine

## Introduction
This small project was mainly developed for demonstration purposes, to show how a minimalistic stack machine operates.

There are two demo programs written, using the machine code:
* A hello world program, showing the syntax;
* A factorial computing program, showing the more advanced features, like procedure calling;

The "machine" allows for basic output, and there is also a *trace* mode, which makes the machine stop at each operation.

## Design

### Memory organization
* code segment;
* stack segment;
* data (heap) segment;

### Registers
* instruction pointer `ip` (program counter);
* stack pointer `sp`;
* frame pointer `fp`;

### Instruction set

The simulated stack machine has a minimalistic instruction set, containing several instruction groups: 
* arithmetic: `IADD`, `ISUB`, `IMUL`; 
* comparison: `ILT`, `ILET`, `IEQ`; 
* memory: `CONST`, `POP`, `LOAD`, `GLOAD`, `GSTORE`; 
* branching: `BR`, `BRT`, `BRF`, `CALL`, `RET`;
* IO: `PRINT`;

Most importantly, the `CALL` and `RET` instructions alow for procedural programming.

Here is a full list of the instruction codes with description on what they do.

instruction | code | arg#0 | arg#1 | arg#2 | description
--- | --- | --- | --- | --- | ---
IADD | 1 | - | - | - | Pops the top two numbers from the stack, adds them, and pushes the result back on the stack.
ISUB | 2 | - | - | - | Pops the top two numbers from the stack, subtracts the topmost from the second `s[-1]-s[0]` (`0`- topmost), and pushes the result back on the stack.
IMUL | 3 | - | - | - | Pops the top two numbers from the stack, multiplies them, and pushes the result back on the stack.
ILT | 4 | - | - | - | Pops the top two numbers from the stack, compares them as `s[-1]>s[0]` (`0`- topmost), and pushes `1` on top of the stack if the condition is met, otherwise pushes `0`.
ILET | 5 | - | - | - | Pops the top two numbers from the stack, compares them as `s[-1]>=s[0]` (`0`- topmost), and pushes `1` on top of the stack if the condition is met, otherwise pushes `0`.
IEQ | 6 | - | - | - | Pops the top two numbers from the stack, compares them as `s[-1]?=s[0]` (`0`- topmost), and pushes `1` on top of the stack if the condition is met, otherwise pushes `0`.
BR | 7 | `address` | - | - | Sets the instruction pointer `ip` to the value of `address`.
BRT | 8 | `address` | - | - | Pops the top number of the stack, and if it is equal to `1`, sets the instruction pointer `ip` to the value of `address`.
BRF | 9 | `address` | - | - | Pops the top number of the stack, and if it is equal to `0`, sets the instruction pointer `ip` to the value of `address`.
CONST | 10 | `value` | - | - | Adds a constant number `value` on top of the stack.
LOAD | 11 | `offset` | - | - | Copies the number `i[fp+offset]`, from stack position `fp+offset` to the top of the stack. Here `fp` is the frame pointer.
GLOAD | 12 | `address` | - | - | Copies a value from the heap, at heap address `address` to the top of the stack.
GSTORE | 13 | `address` | - | - | Pops the topmost number from the stack and saves it in the heap memory at heap address `address`.
PRINT | 14 | - | - | - | Pops the topmost number from the stack and prints it, using the IO interface.
POP | 15 | - | - | - | Pops the topmost number from the stack.
CALL | 16 | `address` | `nargs` | - | First, pushes the number of call arguments `nargs`, the current frame pointer `fp` and the current instruction pointer `ip` on the stack in that order. Next, updates the frame pointer `fp` to the new value of the stack pointer `sp`. Finally sets the instruction pointer to `address` argument. 
RET | 17 | - | - | - | First, pops the topmost number on the stack, to use as a return value. Sets the stack pointer `sp` to the value of the frame pointer `fp`, which was last updated on a `CALL` instruction. Next, pops the three topmost numbers from the stack. The first number is set to the instruction pointer `ip`, the next to the frame pointer `fp`, and the last decreases the stack pointer `sp` by it. This last number is infact the number of arguments of the last `CALL`. Decreasing the stack pointer by the number of arguments effectively discards the arguments, because any subsequent push on the stack will rewrite one of them. Finally, the return value, which was ontop of the stack before the `RET` call, gets pushed back on the stack.
HALT | 18 | - | - | - | Terminates the program execution.