From dba858307d92d95c7167f55922e5df315284ca97 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Sun, 28 Aug 2022 23:24:43 -0400 Subject: [PATCH] Added documentation of all the opcodes in README --- README.md | 170 +++++++++++++++++++++++++++++++++++++++++++++++ creature_test.go | 49 ++++++++++++++ 2 files changed, 219 insertions(+) diff --git a/README.md b/README.md index 16be098..81db4d3 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,173 @@ # creature A simple, extendable, 16 instruction stack machine. + +It has two portions of memory: the stack and the block. I hesitate to call the +block a heap because it is not a data structure, it is a continuous block of +memory. + +Both the stack and the block are as infinite, as computing resources and integer +limits allow, in the positive direction. They are automatically expanded +when written to. + +## Instruction Set + +Each documented instruction has a list of what is pushed, and what is popped. +the items are listed in chronological order, from first pushed/popped to last +pushed/popped. + +### 0x0 PUSH + +Pushes the next word in program memory onto the stack. + +Pushes: +1. next word in program memory + +### 0x1 POP + +Pops the top word off of the stack, and discards it. + +Pops: +1. word + +### 0x2 PEEK + +Reads a memory address from the block and places it atop the stack. + +Pops: +1. address + +Pushes: +1. word found at address + +### 0x3 POKE + +Sets a memory address in the block. + +Pops: +1. address +2. value to store + +### 0x4 ADD + +Adds two words. Tip: this can be used as a logical OR. + +Pops: +1. left operand +2. right operand + +Pushes: +1. left operand + right operand + +### 0x5 SUB + +Subtracts two words. + +Pops: +1. left operand +2. right operand + +Pushes: +1. left operand - right operand + +### 0x6 MUL + +Multiplies two words. + +Pops: +1. left operand +2. right operand + +Pushes: +1. left operand * right operand + +### 0x7 DIV + +Divides two words. + +Pops: +1. left operand +2. right operand + +Pushes: +1. left operand / right operand + +### 0x8 EQ + +Checks if two words are equal. Pushes 1 if true, zero if false. + +Pops: +1. left operand +2. right operand + +Pushes: +1. left operand == right operand + +### 0x9 GT + +Checks if a word is greater than another word. Pushes 1 if true, zero if false. + +Pops: +1. left operand +2. right operand + +Pushes: +1. left operand > right operand + +### 0xA LT + +Checks if a word is less than another word. Pushes 1 if true, zero if false. + +Pops: +1. left operand +2. right operand + +Pushes: +1. left operand < right operand + +### 0xB NEQ + +Checks if two words are *not* equal. Pushes 1 if true, zero if false. + +Pops: +1. left operand +2. right operand + +Pushes: +1. left operand != right operand + +### 0xC MOD + +Performs a modulo operation on two words. + +Pops: +1. left operand +2. right operand + +Pushes: +1. left operand % right operand + +### 0xD HALT + +Halts execution of the machine. + +### 0xE JMP + +Jumps to the specified address if a word is non-zero. + +Pops: +1. address +2. condition + +### 0xF CAL + +Call a function that can be registered using the Machine.Register method. +Functions are allowed to push and pop whatever they want to and from the stack, +as well as read and write to and from the block. + +Pops: +1. function ID +2. ...other stuff, it depends on the function. + +Pushes: +1. ...again, depends on the function. diff --git a/creature_test.go b/creature_test.go index 50a4244..5c3acb9 100644 --- a/creature_test.go +++ b/creature_test.go @@ -227,3 +227,52 @@ func TestJump(test *testing.T) { test.Fail() } } + +func TestRegister(test *testing.T) { + output := "" + machine := &Machine { Program: []int { + PUSH, int('h'), + PUSH, 4, + CAL, + PUSH, int('e'), + PUSH, 4, + CAL, + PUSH, int('l'), + PUSH, 4, + CAL, + PUSH, int('l'), + PUSH, 4, + CAL, + PUSH, int('o'), + PUSH, 4, + CAL, + PUSH, int('r'), + PUSH, 4, + CAL, + PUSH, int('l'), + PUSH, 4, + CAL, + PUSH, int('d'), + PUSH, 4, + CAL, + PUSH, int('!'), + PUSH, 4, + CAL, + }} + machine.Register(4, func(machine *Machine) (stop bool) { + output += string(rune(machine.Pop())) + return + }) + + err := machine.Execute(0) + if err != nil { + test.Log("machine exited with error:", err) + test.Fail() + } + + test.Log("printed:", output) + if output != "hellorld!" { + test.Log("result should be", "hellorld!") + test.Fail() + } +}