Quagmire

An art project where drawings draw themselves.

Quagmire is an emulation of an impossible 8bit processor, where all memory is addressed in 2 dimensions, and is represented by pixel value. Program execution threads can run up, down, left or right. Sections of code are visible in memory, as are the processes as they run. Unlike a normal computer the internal process of the machine is visible. Programs are drawings.

In this system, crashes can be viewed as they occur, processes can write all over each other, or themselves. Lost threads of execution wander through memory, running any data they meander over.

Drawings

This is a series of artworks documenting some of the experimental drawings/programs I have tried with quagmire. In these pictures, the memory contents is shown, with the program threads overlayed as white pixels. Memory is cleared to white (value 255) to make things easier to see, as most instructions are nearly black. The first thread always starts at the bottom left corner heading from left to right.

Fork Exec Exit

A test program to broadly emulate the actions of the commands fork, exec and exit in a unix system - ie copy the code to another location, spawn a new process and exit the parent process. As the new thread is spawned at 90 degrees counter clockwise to the parent, after the 3rd copy, a new process is written in exactly the same position as the original and the drawing is infinitely repeated.

Broken fork bomb

A fork bomb is similar to the program above, except it forks multiple copies of itself, which means memory will fill up and the machine will become inundated with processes. Unfortunately there is a bug in the program, causing the copied processes to overwrite each other causing a crash. Meandering through memory, a process thread manages to rerun the first program, but in reverse, writing to two memory positions in the centre of memory.

Self destruction

I thought of another, simpler method of causing mayhem. This program fills memory with a drawing (the x and y coordinates xor'ed, then and'ed) that eventually overflows and overwrites itself, after that I had no idea what would happen to the program thread. It skips into it's drawing in image 5, and then some localised order follows, lots of threads are spawned and then increasing chaos, as threads fall over each other, writing and executing. At this point I am not sure where the chaos comes from, there is no randomness in the system and it's entirely deterministic. Perhaps it's a pattern which is too hard for me to follow?

Fork bomb

Finally the fork bomb works! I've increased the memory so the drawings are bigger. Each process spawns two copies of itself, and the processes loop back over one another in a similar way to the first drawing. Eventually the copies begin interfering with one another, resulting in one or two lost threads. Interestingly, as the code is copying itself, errors are duplicated in the child threads. Eventually something goes very wrong, and a strange program is created which spawns hundreds of threads, which then go on to make some interesting marks, but eventually settle into a repeating pattern of behaviour.

Old Memories

Technical details

Quagmire reads png images as it's binary format. These can be edited in a normal paint package, but it's not to be recommended. I've written a simple "compiler" that creates images from a text microcode file. The main reason this is easier is that you can insert comments.

The virtual machine has one work register (w) which can be copied to or from memory, or used for processing, sometimes in conjuction with a memory address. Addresses are always two bytes long, and indexed in x,y coordinates.

Instruction set

0x00 nop
0x01 movlw l (write literal to w)
0x02 movf x y (w to mem location)
0x03 movw x y (mem location to w)
0x04 movif x y x y (indirect from w to address)
0x05 moviw x y x y (indirect from address to w)
0x06 and x y (and w with value at x,y)
0x07 or x y (or w with value at x,y)
0x08 not x y (not w with value at x,y)
0x09 xor x y (xor w with value at x,y)
0x0a incw (increment w)
0x0b decw (decrement w)
0x0c add x y (add w with value at x,y)
0x0d rotcw (rotate thread clockwise)
0x0e rotccw (rotate thread counter clockwise)
0x0f jmp x y (move thread to location)
0x10 rotcwz (if w is zero, rotcw)
0x11 rotccwz (if w is zero, rotccw)
0x12 jmpz x y (if w is zero, jmp)
0x13 thrspawncw (spawn a thread clockwise)
0x14 thrpawnccw (spawn a thread counter clockwise)
0x15 thrkill (kill this thread)
0x16 skipz (skip next instruction if w is zero)
0x17 org (reset memory adressing origin to current space)

Memory Addressing

Addresses are relative to the thread's spawn position and direction when it was created.

This is important, so programs don't have to care about the orientation they are running in.

Cellular Automata

Although by appearance these programs may resemble cellular automata such as John Conway's "life" there is really not that strong a relationship. CA's generally process all pixels every calculation step, while quagmire uses a program counter and state similar to a real computer, and distinct instructions to make it easier to program. In a CA like "life", which is a universal machine, it is possible to emulate machine instructions using the emergent behavour of the automata (an approach I considered when initially designing this system). However, it is a indirect and difficult method of programming and I was more interested in creating an emulation that is closer to a normal processor.

Memory Protection

Processes running in real operating systems are allocated areas of memory they are allowed to operate on. This area of memory can be enlarged with the malloc command, but any access outside of this area will result in a "Segmentation Fault", "General Protection Fault", or something similar. The operating system will prevent access outside of this area at all costs, as it will either cause instability, or will be a source of insecurity. There are often ways round this protection by exploiting bugs in a program, fooling the operating system into running code it shouldn't (read about buffer overflow attacks for more info).

As you might be expecting, Quagmire has none of this memory protection, as processes can write over other processes data, and even their program data. This makes Quagmire inherently unstable, and although it will never stop, it will rarely do what you'd expect.

Source code

The source code is availible under the GPL licence here: quagmire-1.0.0.tar.gz
See the README file for more info on building etc.

Links

Befunge
A text language similar to, and even more nuts than quagmire.

Runme
Say it with software art!

Code Art Brutalism
A paper on low level systems and simple programs by Simon Yuill.

My site
Dave's page of art and programming.

Creative Commons Licence
This work is licenced under a Creative Commons Licence.