You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Sarah Jamie Lewis 01cc63c7f1 Initial Commit 11 months ago
.idea Initial Commit 11 months ago
src Initial Commit 11 months ago
.gitignore Initial Commit 11 months ago
Cargo.lock Initial Commit 11 months ago
Cargo.toml Initial Commit 11 months ago Initial Commit 11 months ago
charset.asm Initial Commit 11 months ago
display.asm Initial Commit 11 months ago
example.asm Initial Commit 11 months ago
strings.asm Initial Commit 11 months ago
util.asm Initial Commit 11 months ago

Philosophy of Boo OS

Operating System: An operating system is a collection of things that don't fit into a language. There shouldn't be one. - Design Principles Behind Smalltalk

Boo OS is a meditation on recursive complexity and the curse of simplicity. In an age where computers are so powerful, it is sometimes healing to start again.

I have often been stuck between my desire to build either an operating system, a shell, a language or an ide. None of those categories ever quite fit the hole I was intending them to fill.

After much introspection and research I finally decided that what I really needed was something different.

Inspired by smalltalk, Boo OS is "image" based, the entire system can be dumped and reloaded to the same state.

Eventually my plan is that Boo OS contain all the essentials necessary for self modification. It should be possible to (safely) modify the operating system from within the operating system and have the changes take effect.

How that will look is undecided. For now, Boo OS is coded entirely in Boo Bytecode Assembly Language and assembled using a Rust based assembler. One of my first targets for a real application is an Assembler written in Boo Bytecode, run on BooOS and outputting a Boo Bytecode image.


Boo OS is written in Boo Bytecode which is run by the Boo Virtual Machine (BooVM). BooVM and Boo Bytecode is inspired by various retro computing architectures with minimal instructions, but a focus on integrating with the core systems.

As such. the BooVM offers minimal integration with the outside world. Interaction is limited to:

  • Reading and Writing BooVM images to/from the Host OS
  • Exposing The State of the Keyboard and Mouse
  • Offering a Framebuffer for Display Output
  • (Provisional) Reading and Writing "Files" from the Host OS OR Loading and Interacting with a generalized File System that can be loaded by both operating systems (i.e. some kind of virtual disk image)

Why Write a Custom VM?

Why Not? This is a meditation on recursive complexity. I was already set on writing a new language and building one from the ground up on a custom instruction set seemed like a great idea.

The longer version is that I looked into many options for the base of this project. They fell into two main categories:

The first featured existing ISA emulations (e.g. QEMU) and existing production ready language virtual machines (e.g. JVM, Lua) - I decided that using an existing architecture wasn't in the spirit of the project. Further, both of these options would require extra work to integrate a framebuffer display and input up to the extent where I would be writing an OS for an existing architecture. I wanted to keep the wrapping interface to the host OS as simple as possible.

The second category featured older reto architectures, emulators and the like. I rejected this approach because there are some details I don't want to care about, like scanlines and cartridge layouts. This approach would also make interaction with the Host OS a project in itself likely requiring forking and significant rework resulting in a custom emulator any way.

After research, designing and implementing an assembler for some custom bytecode and building a small VM to run it seemed to be the simplest option and provides me with a lot of freedom moving forward, and lends itself to infinite experimentation.


The below represents some ideas for projects to tackle within Boo OS.

  • Print Strings to the FrameBuffer
    • Set Framebuffer Position Helper Function
    • put_char Helper Function
  • Memory Management
    • Heap Design
    • Implement Helper Functions alloc and free
    • Memory Safety
  • Keyboard Input
    • Designing Input Interaction (poll v.s. interrupts)
  • Create a Console Shell to Interact with the System
    • At first this shell will be limited to pre-programmed commands
    • But, it should quickly all the construction of new commands from old ones
    • Finally, the shell should facilitate saving and loading of images
  • Write a Bootstrapped Assembler Application in Boo Bytecode Assembly

Formal Reqs

Run time:

  • Memory needs R/W/E flags - 3 bits

  • Mapping Memory before handing off to lesser privileged processes

  • Needs some understanding off operating mode

  • Never attempt to pop an empty stack


We treat each 64 chunks of memory as a single page:

    0x0000  4800 Pages of Write only Display Memory
    0x4B000 1 Page of Registers [rip, mode, display, rax, r2, r3, r4, r5, r6, r7, r8]
    0x4B040 1 Page of Call Stack
    0x4B080 1 Page of Input Flags (Keys Down etc)
    0x4B0C0 Dynamic Memory Begins


All instructions are fixed length.

Meta Instructions

0x00 - Nop 0x01 - Update Display 0x0F - HLT

Dynamic Instructions

Prefix 0x1#,0x2#,0x3# are given to dynamin register based commands

  • 0x1n STORE(n) $Addr (R(n)) -> Addr)

  • 0x2n LOAD(n) $Addr (Addr -> R(n))

  • 0x3n LOADI(n) IMM (Immediate -> R(n))

  • 0x4n INC(n)

  • 0x5n DEC(n)

  • 0x6n ISTORE(n)

  • 0x7n x LDSTORE Load the Address Stored in n into reg(x)

  • 0x8n x Transfer R(n) to R(x)

  • 0x9n Shift


Prefix 0xa# is given to arithmetic functions

  • 0xa1 ADD (R2 + R3 -> RAX)
  • 0xa2 SUB (R2 - R3 -> RAX)
  • 0xa3 MUL (R2 * R3 -> RAX)
  • 0xa4 DIV (R2 / R3 -> RAX)
  • 0xa5 SHIFT (R2 >> R3 -> RAX)
  • 0xa6 AND (R2 & R3 -> RAX)


Prefix 0xc# allows call stack manipulation. The machine denotes 64 memory addresses at memoo

  • 0xc0 RET
  • 0xc1 PUSH Call Stack

Jumps and Branches (0x5#)

  • 0xE0 JMP $Addr - Unconditional jump to $Addr
  • 0xE1 JMPEQ $Addr (if R1 == R2 jmp $Addr else )
  • 0xE2 JMPNEQ $Addr (if R1 != R2 jmp $Addr else )
  • 0xE3 JMPGT $Addr (if R1 > R2 jmp $Addr else )
  • 0xE4 JMPLT $Addr (if R1 < R2 jmp $Addr else )
  • 0xE5 JMPGEQ $Addr (if R1 >= R2 jmp $Addr else )
  • 0xE6 JMPLEQ $Addr (if R1 <= R2 jmp $Addr else )

Admin Mode Instructions

Instructions prefixed with 0xF are admin instructions

  • 0xF0 UNSET_R $Addr (Sets the 64 addresses after $Addr as Not Readable)

  • 0xF1 SET_R $Addr (Sets the 64 addresses after $Addr as Readable)

  • 0xF2 UNSET_W $Addr (Sets the 64 addresses after $Addr as Not Writable)

  • 0xF3 SET_W $Addr (Sets the 64 addresses after $Addr as Writable)

  • 0xF4 UNSET_X $Addr (Sets the 64 addresses after $Addr as Not Executable)

  • 0xF5 SET_X $Addr (Sets the 64 addresses after $Addr as Executable)

  • 0xFF DROP_MODE $Addr - Drops from Admin Mode into User Mode (No access to Admin mode instructions)

0: LOAD_IMM 10 1: NOP 2: DEC(1) 3: JNEQ