BF Interpreter on The PCJr

January 22, 2016

old school computing


The PCJr was a failure of a computer created by IBM in the 80’s. At its heart is the Intel 8088 CPU. CSH happened to acquire one back in the day, and another more recently after a member interned at IBM. For a hackathon a few friends and I decided to try and write an OS for the machine. Our original goal was to get a lisp interpreter running on it, and try and emulate a TCP stack using the PCJunior’s serial port. We fell short on all our goals, so in a last ditch effort I used the base kernel we developed and wrote a small BF interpreter.

CSH BrainFuck

The BF Language

BF is a very simple language. The easiest way to think about BF is as a series of operations on a pointer into an array. The simplest specification for bf is below.

State

Variable Description
array An array of 30K bytes
ptr The pointer into the array
iptr The current instruction being executed

Instructions

Instruction Description
< Decrement the pointer
> Increment the pointer
- Decrement the value at the pointer
+ Increment the value at the pointer
. Print out the value at the pointer
, Set the value at the pointer to a single character from input
[ Loop start, skip to matching ] if value at pointer is 0
[ Loop end, jump to matching [ if value at pointer is not 0

A full, but simple BF program looks like this.

    ,>,<[>[->+>+<<]>>[-<<+>>]<<<-]>>.

This program takes 2 numbers in cells 1 and 2 and multiplies them together and puts the result in cell 3. BF programs are very verbose, but the core concepts are pretty simple.

The Interpreter Implementation

The interpreter is pretty simple, and is only 346 lines total. The main loop of the reads key presses using an interrupt, and uses them to fill a buffer. When enter is pressed the entire program is then parsed and executed.

Building the Loop Table

The interpreter goes through two phases in order to execute the brainfuck code. The first phase is the loop phase which looks for loop statements within the input code and builds a table of jump offsets so it can make the actual looping logic easier to write. Instead of making a complex stack during run time we do our loop test and then if we need to exit the loop we just lookup the jump position in our jump table.

Running the Code

To actually run through the code the interpreter starts at the first address in the input buffer and moves forward, keeping track of its position using an instruction pointer. Actual evaluation is done by a big long chain of cmp statements.

Future Work

I’m currently working on a memory allocator and scheduler for the kernel. Once those are finished I plan on making a more complete operation system including a shell of some kind.

Shout Outs

Rob Glossop and James Forcier are also working on the OS with me, and contributed significant parts.

More Pictures

Example of BF Running on actual hardware

View post on imgur.com

X86: Compatible To the Ends of the Universe

backwards compatibility!