ldc 3 // a ldc 4 // a, b lds -1 // a, b, a lds -1 // a, b, a, b mul // a, b, a*b ldc 4 // a, b, a*b, 4 sub // a, b, a*b-4 sts -2 // a*b-4, b
ldc 3 // a ldc 4 // a, b lds -1 // a, b, a lds -1 // a, b, a, b mul // a, b, a*b ldc 4 // a, b, a*b, 4 sub // a, b, a*b-4 sts -2 // a*b-4, b ne brt NE // a*b-4, b ldc 0 // a*b-4, b, 0 str RR // a*b-4, b, RR=0 bra DONE // a*b-4, b, RR=0 NE: ldc 1 // a*b-4, b, 1 str RR // a*b-4, b, RR=1 DONE: halt
ldc 3 // 3 ldc 4 // 3, 4 bsr SUMSQUARE // 3, 4, PC ajs -2 // -empty-stack- ldr RR // SUMSQUARE: our answer 25 bra DONE SUMSQUARE: link 1 // 3, 4, PC, MP, x ldl -3 // 3, 4, PC, MP, x, 3, 3 ldl -3 // 3, 4, PC, MP, x, b, a mul // 3, 4, PC, MP, x, 9 ldl -2 // 3, 4, PC, MP, x, 9, 4 ldl -2 // 3, 4, PC, MP, x, 9, 4, 4 mul // 3, 4, PC, MP, x, 9, 16 add // 3, 4, PC, MP, x, 25 stl 1 // 3, 4, PC, MP, 25 ldl 1 // 3, 4, PC, MP, 25, 25 str RR // 3, 4, PC, MP, 25 RR=25 unlink 1 // 3, 4, PC ret // 3, 4 DONE:
bra MAIN // 0: FAC: link // 1: N, 21, MP ldl -2 // 2: N, 21, MP, N LDC 1 // 3: N, 21, MP, N, 1 le // 4: N, 21, MP, true/false brt FAC-BASE // 5: N, 21, MP ldl -2 // 6: N, 21, MP, N ldl -2 // 7: N, 21, MP, N, N LDC 1 // 8: N, 21, MP, N, N, 1 sub // 9: N, 21, MP, N, N - 1 bsr FAC // 10: N, 21, MP, N, N - 1, 2 ldr RR // 11: mul // 12: N * factorial (N - 1) bra FAC-DONE // 13: FAC-BASE: LDC 1 // 14: N, 21, MP, 1 FAC-DONE: str RR // 15: N, 21, MP RR=1 unlink // 16: N, 21 sts -1 // 17: 21 ret // 18: MAIN: LDC 20 // 19: N = 20 bsr FAC // 20: N, 21 FAC ( 20 ) bra DONE DONE: halt
bra MAIN FAC: link 1 // fac( int n ) LDC 1 // int res = 1 stl 1 FACTEST: ldl -2 // while ( n > 1 ) LDC 1 gt brf FACEND ldl -2 // res = res * n ldl 1 mul stl 1 ldl -2 // n = n - 1 LDC 1 sub stl -2 bra FACTEST FACEND: ldl 1 // return( res ) str RR unlink sts -1 ret MAIN: LDC 6 bsr FAC // fac( 6 ) halt
This is the Simple JavaScript Stack Machine. It can be programmed to execute a simple set of assembly-like instructions on a simulated stack machine.
I recommend using the JavaScript console that is part of WebKit's Web Inspector in either Google Chrome or Safari.
Have fun!
The follwing is a short overview of how the app can be used from the JavaScript console in your browser.
An SJSSM object has to be instantiated to start using the machine:
> machine = new SJSSM;
< Object
Code can be loaded directly into the machine by using the program() method and passing your source as an argument. Check the instruction set reference for documentation on the available instructions.
To get started quickly, there are some predefined code blocks available, that can be used to program the machine. These can be loaded from the source of this page using jQuery, like this:
> machine.program($('#sjssm > #simplemath').text());
< undefined
The example above uses simple categorization under the #sjssm collection.
The available example code blocks in #sjssm are:
You can, of course, easily add your own programs to this page. Just view the page source. The programs are at the beginning of the body-tag. If you want to, you can create your own categories.
You can find an overview of all categories and programs in the program index.
The machine can be started with the following statement, which makes it run the code that is currently loaded:
> machine.run(); < ... < undefined
Note that the run() method does not return anything. In fact, running the machine does not have any predefined result or even a purpose. If your code does do something useful, you probably want to get some data from a register or from the stack, in which case you can use these inspection statements.
Instead of starting the machine and letting it execute a program until it thinks it is done, the step() method can be used to let the machine execute a fixed number of steps and then wait. This can be useful when debugging and inspection of the machine is needed while a program is still executing. The machine can be stepped with the following statement:
> machine.step(2);
< true
The step() methow will return either true or false, indicating the success or failure of the last step. When a step fails, additional information will be printed to the console.
The machine can be resetted with the following statement, which sets all its registers to the startup values, empties the stack and clears any currently loaded code:
> machine.reset();
< undefined
The machine can reveal several internal properties that are interresting for the user, such as its registers, the stack and the loaded code:
> machine.getRegisters(); < Object > machine.getRegisters().RR; < 42 > machine.getStack(); < [3, 5, ...] > machine.getCode(); < [Object, Object, Object, ...]
This is a full index of all predefined programs found in the page source. Click on a program's name to expand the code listing.
This section documents the machine's registers, it's instruction set and some important concepts used in the machine implementation.
The SJSSM is simple and has a minimal number of registers. The registers currently implemented are the minimum required for a functional stack machine that supports the current instruction set.
Register | Name | Description |
---|---|---|
Program Counter | PC | Stores the program counter, which points to the next executed instruction in the program loaded into the machine. |
Stack Pointer | SP | Stores the stack pointer, which points to the top of the stack. |
Mark Pointer | MP | Stores the mark pointer, which points to a previously marked position in the stack. |
Return Register | RR | Stores arbitrary values, which are, for example, returned from subroutines or otherwise put there by the program. |
Interrupt Register | IR | This register is not used currently. |
Labels are used to mark lines in the machine code. They can be used when jumping to a specific location in the code (branching). Branching is used in flow control and for executing subroutines.
The main purpose of using labels is to eliminate the need to use static numeric values to reference positions in a program's code, making code easier to read, edit and understand.
See the instruction set reference for instructions that use labels.
The following table gives a complete overview of the instruction set available in SJSSM.
All the instructions have either 1 parameter or none at all. Instructions that take registers as an argument should use one of the registers from the register reference.
Instruction | Op | Param | Description | Example |
---|---|---|---|---|
Halt machine | halt | Halt the machine to make it stop executing code. | halt |
Instruction | Op | Param | Description | Example |
---|---|---|---|---|
Load constant | ldc | number | Push a numeric value onto the stack. | ldc 42 |
Load from register | ldr | register | Push the value in the specified register onto the stack. | ldd RR |
Load from stack (SP) | lds | offset | Push the value at the position in the stack indicated by the specified offset, relative to the stack pointer, onto the stack. | lds -1 |
Load from stack (MP) | ldl | offset | Push the value at the position in the stack indicated by the specified offset, relative to the mark pointer, onto the stack. | ldl -2 |
Store in register | str | register | Pop the top most value from the stack and store it in the specified register. | str RR |
Store in stack (SP) | sts | offset | Pop the top most value from the stack and store it in the stack at the position specified by the offset, relative to the stack pointer. | sts -3 |
Store in stack (MP) | stl | offset | Pop the top most value from the stack and store it in the stack at the position specified by the offset, relative to the mark pointer. | stl -2 |
Adjust stack | ajs | adjustment | Given a positive or negative value specified by the adjustment, grow or shrink the stack, by pushing empty values or popping existing values onto or from the stack, respectively. | ajs -2 |
Instruction | Op | Param | Description | Example |
---|---|---|---|---|
Addition | add | Pop the top two values from the stack, add them, and push the result back. | add | |
Subtraction | sub | Pop the top two values from the stack, subtract them, and push the result back. | sub | |
Multiplication | mul | Pop the top two values from the stack, multiply them, and push the result back. | mul | |
Division | div | Pop the top two values from the stack, divide them, and push the result back. | div | |
Modulation | mod | Pop the top two values from the stack, take the modulo, and push it back. | mod | |
Negation | neg | Pop the top value from the stack, negate it, and push the result back. | neg |
Instruction | Op | Param | Description | Example |
---|---|---|---|---|
Equals | eq | Pop the top two values from the stack, compare them, and push a true value back onto the stack if they're equal, else push a false value. | eq | |
Not equals | ne | Pop the top two values from the stack, compare them, and push a true value back onto the stack if they're not equal, else push a false value. | ne | |
Greater then | gt | Pop the top two values from the stack, compare them, and push a true value back onto the stack if the first is greater then the second, else push a false value. | gt | |
Less then | lt | Pop the top two values from the stack, compare them, and push a true value back onto the stack if the first is less then the second, else push a false value. | lt | |
Greater or equals | ge | Pop the top two values from the stack, compare them, and push a true value back onto the stack if the first is greater then or equal to the second, else push a false value. | ge | |
Less or equals | le | Pop the top two values from the stack, compare them, and push a true value back onto the stack if the first is less then or equal to the second, else push a false value. | le |
Instruction | Op | Param | Description | Example |
---|---|---|---|---|
Branch if true | brt | label | Pop the top most value from the stack, check if it's true. If so jump to the position specified by label. | brt DOTRUE |
Branch if false | brf | label | Pop the top most value from the stack, check if it's false. If so jump to the position specified by label. | brf DOFALSE |
Branch always | bra | label | Immediately jump to the position specified by label. | brf DOALWAYS |
Branch to subroutine | bsr | label | Push the current value from the PC-register onto the stack, and then jump to the position specified by label. | bsr SUBRTN |
Return | ret | Pop the top most value of the stack, and 'return' to it, by jumping to the position indicated by that value. | ret |
Instruction | Op | Param | Description | Example |
---|---|---|---|---|
Link subroutine | link | number | Links a subroutine, by:
|
link 2 |
Unlink subroutine | link | number | Unlinks a subroutine, by:
|
unlink 2 |