DescriptionThis is a virtual computer that can be programmed in its own form of assembly language. I designed every aspect of the computer. It's a very minimalist, stack-based computer. The folder containing the computer also contains several assembly programs which I have written for the computer. I look forward to seeing what other people can make with it. Enjoy!
Instructions for assembly program LIFE:
Switch to eraser or pen with B. Start life simulation with A.
Instructions for assembly program BF:
Copy a brainfuck program separated from its input by ! into the clipboard and run the program. Press A for fast mode and B for slow mode.Instructions
The smileBASIC program is an emulator for a very simple virtual computer that I designed. The computer has a very small instruction set, consisting of just 30 instructions and it is a purely 16-bit machine. The RAM addresses are 16-bit and each address stores a 16-bit number. The instructions push and pop items on a descending empty stack. With one exception, every operation gets its operands from the stack.
There are four registers, none of which are general purpose. The instruction pointer stores the address in memory of the currently executing instruction. The upper and lower display pointers set the address in memory which the screens read from. Each screen is a 32x16 or (20x10 in hexadecimal) grid of characters that displays each address in RAM as a character. The stack pointer stores the address in memory which the next push instruction will store a number in.
There are 64 kilowords of RAM or 128 kilobytes. Everything that the computer needs is stored in this single array of RAM. This includes the program, the stack, the screen memory and any data that the program is using. This allows for self-modifying code and reading of items below the top element of the stack.
There is only one flag and it is set when an addition or subtraction causes an overflow or underflow and reset when another addition or subtraction operation is performed which does not. It is used for conditional branching.
How to use the computer
Start the program ASSEMBLER and you will be prompted to enter a program to load. Typing nothing here will use the contents of program slot 1 as the program to load. If a file is loaded, it is stored in slot 1.
Quick load allows for very fast compilation of programs. After compiling a program, saving the contents of program slot 2 will make a "quick load" version of the program. When loading a quick loading program, enter 1 for quick load, otherwise enter 0. If you have already compiled the program you are currently working on, entering 2 here will quick load the program from slot 2 (where compiled programs are stored). Do not overwrite a program with its quick loading version as all readability and comments will be lost. I have saved my quick loading programs with the prefix "Q" or "QL".
Debug mode displays the contents of registers during execution. See "programming the virtual computer" for more details. Enter 1 for debug mode to be on, enter 0 for it to be off.
Refresh mode refreshes the display once per instruction rather than once per refresh instruction. Enter 0 to refresh only on refresh instructions, enter 1 to refresh once per instruction.
After these prompts, the program is loaded and compiled. You can see the progress of the compilation on the screens while it is happening. The first pass is white, the second pass is red, third yellow and final pass green.
While the program is running, the upper and lower screens both display 32x16 grids of characters in the centre of the display. If debug mode is on, debug information is displayed. After a program ends, text output will display in the upper left corner of the upper screen and a beep will sound. The word "END" will also display on the lower screen.
The instruction pointer is red and green and the stack pointer is blue and yellow. These should ideally never be visible during normal program operation!
Programming the virtual computer
Load ASSEMBLER into program slot 0, then write your program in program slot 1. While working on the program, execute it by typing nothing at the load prompt.
Debug mode is provided to provide some help when writing your program. When enabled, the program will be paused by default. It can be stepped using the c-stick. The next instruction that will execute is displayed at the top of the upper screen. The contents of the registers are displayed along with the contents of RAM at the address that they store in decimal on the upper screen and hexadecimal on the lower screen. Unpause the program by holding the circle pad away from its neutral position and stepping through the program, then returning the circle pad to neutral. Old 3DS owners will require a circle pad pro accessory or they will have to modify the ASSEMBLER program to work without the c-stick/circle pad pro. Debug info only refreshes when the screens refresh, so it is helpful to run debug mode with refresh mode enabled too.
Instruction vsync is an option accessed by enabling debug mode. This will delay the program by a set number of frames for every instruction, slowing the program down.
The memory peek utility can be enabled by typing 1 at the prompt. Typing 0 will disable it.
The memory peek utility is accessed by touching the screen and stepping once. This allows you to view the contents of any memory address range or just the stack. Tap the screen to display the next memory addresses and a final tap exits the utility. This may also be accessed by holding L+R after a program finishes execution.
The displays read from RAM and display it from left to right and top to bottom. If you want to put anything on the display, you must ensure that the display pointers are set correctly and that you are writing to an address that would be visible.
The registers are all initialised to 0 except for the stack pointer which is initialised to 65535.
The compiler uses very strict and rather non-standard syntax. Absolutely no extra characters should be present anywhere in the program, otherwise it may not work. Fortunately, comments are possible.
Every line of the program represents a word of RAM. A punctuation mark at the start of every line tells the compiler what kind of data it is seeing. Instructions must be in all caps and a newline represents a new word in memory.
/ 4-digit hex number
B 16-bit binary number
# 5-digit decimal number
< label reference
Numbers may optionally have leading zeroes, but do not require them, a fact that I discovered only while writing this document. This is why my code is full of leading zeroes!
A character code can be used by putting a character after !. This is used for printing letters on the screen for example.
Labels and relocation are what make the compiler more powerful and easier to use. A label names an address in memory. It is comparable to @ in smileBASIC. To make a label, type > followed by a name. To use a label, type < followed by the label you wish to use.
Relocation allows the compiler to place code or data anywhere in RAM. An asterisk followed by any number will change the current address of RAM being written to when the compiled program is being loaded into RAM. For example, the code of a program could be placed at address /1000 and a few instructions at the start of memory could jump to it. Relocation also allows for simulation of variables. Relocate to the position that you want a variable to be stored in and place a label there. To change the contents of the variable, you can push <variablename and write to it. To read from it, you can push the name of the variable and follow it with a read command. You can see this technique used in the example programs that I provided.
The instructions for the virtual computer usually take arguments from the stack and output by pushing to the stack.
The "core" instructions:
The push instruction pushes the contents of RAM immediately after it to the stack. In programs it will usually be followed by a number. Push increments the instruction pointer by 2 rather than one.
Jump pops an element from the stack and sets the instruction pointer to it.
Pushes current value of instruction pointer.
Short for "up display", this pops an element and sets the upper display pointer to it.
Pushes current value of upper display pointer.
Short for "down display", this pops an element and sets the lower display pointer to it.
Pushes current value of lower display pointer.
Decrement the stack pointer.
Increment the stack pointer.
Pop an element and set the stack pointer to it.
Pushes the current value of the stack pointer.
Pops an element and performs a vsync instruction for that number of frames.
Refreshes the display.
Stop the program.
Pops two elements, pushes logical AND of those two elements.
Pops two elements, pushes logical OR of those two elements.
Pops two elements, pushes logical XOR of those two elements.
Pops one element, pushes logical NOT of element.
Pops two element, pushes sum of both elements.
Pops elements 1 and 2, pushes element 1-element 2.
Pops elements 1 and 2, pushes element 1 mod element 2.
Short for "input screen", pushes y-coordinate, x-coordinate and the presence or absence of a touch (touch present=1, touch absent=0)
Short for "input button", pushes current value of button(0).
Pops an element. If that element is zero, then push contents of clipboard in forwards order (popping an element will give the last character of clipboard). If it is non-zero, push contents of clipboard in reverse order (popping an element will give the first character of clipboard).
Pops an element and writes it as a character to the output string.
Pops elements 1 and 2, then performs BEEP element 2, element 1.
Short for "branch if zero", pop elements 1 and 2. if element 2 is zero, jump to element 1.
Short for "branch on overflow", pop an element and jump to it if overflow/underflow flag is set.
Pop an element and push the contents of RAM at address given by that element.
Pop element 1 and element 2, write element 2 to memory address given by element 1.
Pop two elements and push them back so that they have swapped positions.
Pop an element and push it twice.NotesPlease post codes for any assembly programs you've made in the commments!
This program requires the c-stick or circle pad pro in debug mode. Running assembly programs without debug mode on should work fine without the c-stick.