Soul of a tiny new machine. More thorough tests → More comprehensible and rewrite-friendly software → More resilient society.
Go to file
Kartik Agaram c6b928be29 7841 2021-03-03 11:04:07 -08:00
apps 7841 2021-03-03 11:04:07 -08:00
archive 6206 2020-04-17 01:33:51 -07:00
atom 5868 2020-01-02 12:27:35 -08:00
baremetal 7840 2021-03-01 23:49:53 -08:00
html 7834 2021-03-01 14:59:37 -08:00
tools 7746 2021-02-14 16:48:02 -08:00
.gitattributes 6690 2020-07-30 21:39:19 -07:00
000organization.cc 5704 2019-10-19 14:44:54 -07:00
001help.cc 7033 2020-10-14 21:45:24 -07:00
002test.cc 7033 2020-10-14 21:45:24 -07:00
003trace.cc mu.subx: 6 failing tests remaining 2020-05-22 14:45:54 -07:00
003trace.test.cc 5485 - promote SubX to top-level 2019-07-27 17:47:59 -07:00
010vm.cc 7094 2020-10-24 23:15:39 -07:00
011run.cc 6207 - tweaks while creating a video 2020-04-19 09:32:46 -07:00
012elf.cc Raise an error if too few arguments are provided 2019-10-22 19:28:12 -07:00
013direct_addressing.cc Use size-specific MAX/MIN constants 2020-10-22 13:21:07 -07:00
014indirect_addressing.cc . 2020-10-24 20:28:06 -07:00
015immediate_addressing.cc 7133 2020-10-28 01:11:23 -07:00
016index_addressing.cc 7089 2020-10-22 00:59:46 -07:00
017jump_disp8.cc 6911 - comparing floats 2020-09-30 22:53:14 -07:00
018jump_disp32.cc 6911 - comparing floats 2020-09-30 22:53:14 -07:00
019functions.cc 7090 2020-10-24 20:54:44 -07:00
020byte_addressing.cc 7412 - drawing pixels to screen 2020-12-26 19:13:23 -08:00
021div.cc 7092 2020-10-24 21:18:35 -07:00
022float.cc 7131 2020-10-28 00:39:10 -07:00
029syscalls.cc 7092 2020-10-24 21:18:35 -07:00
030translate.cc 6397 2020-05-24 22:43:18 -07:00
031transforms.cc 5863 2020-01-02 01:28:24 -08:00
032operands.cc 6892 2020-09-27 23:28:29 -07:00
033check_operands.cc 6957 2020-10-05 10:25:25 -07:00
034check_operand_bounds.cc 6887 2020-09-27 22:05:11 -07:00
035compute_segment_address.cc 6887 2020-09-27 22:05:11 -07:00
036labels.cc 7455 2020-12-28 23:20:14 -08:00
037global_variables.cc 6887 2020-09-27 22:05:11 -07:00
038literal_strings.cc 6397 2020-05-24 22:43:18 -07:00
039debug.cc 6123 - runtime helper for initializing arrays 2020-03-11 17:21:59 -07:00
040tests.cc 6397 2020-05-24 22:43:18 -07:00
100.txt 7439 - start translating Mu programs to baremetal 2020-12-28 11:09:30 -08:00
101_write.subx 6612 - reorganize layers 2020-07-05 12:13:28 -07:00
102test.subx 6612 - reorganize layers 2020-07-05 12:13:28 -07:00
103kernel-string-equal.subx 6627 2020-07-10 21:08:26 -07:00
104new-segment.subx 6612 - reorganize layers 2020-07-05 12:13:28 -07:00
105string-equal.subx 7544 2021-01-22 22:15:17 -08:00
106stream.subx 6612 - reorganize layers 2020-07-05 12:13:28 -07:00
107trace.subx 7782 - baremetal: provide a trace stream 2021-02-22 12:59:57 -08:00
108write.subx 7101 - tile: remove quotes when evaluating strings 2020-10-25 18:45:11 -07:00
109stream-equal.subx 6769 - support for creating fake files in Mu tests 2020-09-10 23:00:19 -07:00
110stop.subx 6612 - reorganize layers 2020-07-05 12:13:28 -07:00
111read.subx 6612 - reorganize layers 2020-07-05 12:13:28 -07:00
112read-byte.subx 6908 - compiling all floating-point operations 2020-09-30 21:17:37 -07:00
113write-stream.subx 6612 - reorganize layers 2020-07-05 12:13:28 -07:00
114error.subx 6612 - reorganize layers 2020-07-05 12:13:28 -07:00
115write-byte.subx 7817 2021-02-27 06:55:41 -08:00
116write-buffered.subx 6612 - reorganize layers 2020-07-05 12:13:28 -07:00
117write-int-hex.subx 6946 - print floats somewhat intuitively in hex 2020-10-04 11:18:23 -07:00
118parse-hex-int.subx 6781 - new app: RPN (postfix) calculator 2020-09-15 22:52:41 -07:00
119error-byte.subx 6612 - reorganize layers 2020-07-05 12:13:28 -07:00
120allocate.subx 7526 2021-01-16 09:29:21 -08:00
121new-stream.subx 6727 - bugfix in a multiply instruction 2020-08-22 14:35:44 -07:00
122read-line.subx 6612 - reorganize layers 2020-07-05 12:13:28 -07:00
123slice.subx 6627 2020-07-10 21:08:26 -07:00
124next-token.subx 6632 2020-07-11 00:11:39 -07:00
125write-stream-data.subx 6612 - reorganize layers 2020-07-05 12:13:28 -07:00
126write-int-decimal.subx 6821 - highlight words clobbered by the next word 2020-09-20 13:42:13 -07:00
127next-word.subx 7329 - snapshot: advent day 4 part 2 2020-12-04 23:02:53 -08:00
128subx-words.subx 6632 2020-07-11 00:11:39 -07:00
129emit-hex.subx 6612 - reorganize layers 2020-07-05 12:13:28 -07:00
130emit.subx 6612 - reorganize layers 2020-07-05 12:13:28 -07:00
131table.subx 6627 2020-07-10 21:08:26 -07:00
132slurp.subx 6612 - reorganize layers 2020-07-05 12:13:28 -07:00
133subx-widths.subx 6632 2020-07-11 00:11:39 -07:00
134emit-hex-array.subx 6612 - reorganize layers 2020-07-05 12:13:28 -07:00
135next-word-or-string.subx 6612 - reorganize layers 2020-07-05 12:13:28 -07:00
200.txt 6612 - reorganize layers 2020-07-05 12:13:28 -07:00
201register-names.subx 6902 2020-09-29 19:24:29 -07:00
202write-int.subx 6612 - reorganize layers 2020-07-05 12:13:28 -07:00
203stack.subx 7483 2021-01-09 08:46:37 -08:00
300.txt 7109 2020-10-25 22:32:56 -07:00
301array-equal.subx 7223 2020-11-11 20:51:17 -08:00
302stack_allocate.subx 7254 2020-11-17 01:06:43 -08:00
303kernel-string.subx 6612 - reorganize layers 2020-07-05 12:13:28 -07:00
304screen.subx 7237 2020-11-14 20:27:43 -08:00
305keyboard.subx 7310 - advent day 1 part 1 2020-12-01 00:32:43 -08:00
306files.subx 7224 2020-11-11 21:04:22 -08:00
307size.subx 6612 - reorganize layers 2020-07-05 12:13:28 -07:00
308allocate-array.subx 7254 2020-11-17 01:06:43 -08:00
309stream.subx 7100 - tile: render string literals 2020-10-25 18:14:12 -07:00
310copy-bytes.subx 7254 2020-11-17 01:06:43 -08:00
311decimal-int.subx 7310 - advent day 1 part 1 2020-12-01 00:32:43 -08:00
312copy.subx 7225 2020-11-11 23:25:55 -08:00
313index-bounds-check.subx 7525 2021-01-16 09:06:01 -08:00
314divide.subx 7290 2020-11-27 21:37:20 -08:00
315slice.subx 7331 - hacky way to convert slice to string 2020-12-04 23:02:53 -08:00
400.mu 7331 - hacky way to convert slice to string 2020-12-04 23:02:53 -08:00
401test.mu 6687 - stream-empty? and stream-full? 2020-07-30 19:34:29 -07:00
402time.mu 7690 2021-02-07 00:20:29 -08:00
403unicode.mu 7690 2021-02-07 00:20:29 -08:00
404stream.mu 6769 - support for creating fake files in Mu tests 2020-09-10 23:00:19 -07:00
405screen.mu 7817 2021-02-27 06:55:41 -08:00
406int32.mu 7290 2020-11-27 21:37:20 -08:00
407right-justify.mu 7690 2021-02-07 00:20:29 -08:00
408float.mu 7276 2020-11-26 11:36:29 -08:00
409print-float-hex.mu 7294 2020-11-28 08:31:55 -08:00
410file.mu 7690 2021-02-07 00:20:29 -08:00
411string.mu 7690 2021-02-07 00:20:29 -08:00
412print-float-decimal.mu 7817 2021-02-27 06:55:41 -08:00
LICENSE.txt 7489 - include GNU Unifont 2021-01-09 18:20:28 -08:00
README.md 7834 2021-03-01 14:59:37 -08:00
bootstrap 5865 2020-01-02 02:01:41 -08:00
bootstrap.md 6618 - new docs 2020-07-06 01:05:10 -07:00
build Remove CC 2020-10-25 12:29:21 -07:00
build_and_test_until 5865 2020-01-02 02:01:41 -08:00
cheatsheet.pdf 5485 - promote SubX to top-level 2019-07-27 17:47:59 -07:00
clean 5865 2020-01-02 02:01:41 -08:00
editor.md 6618 - new docs 2020-07-06 01:05:10 -07:00
exuberant_ctags_rc 6081 - ctags for .mu files 2020-03-05 18:29:00 -08:00
init.linux 7225 2020-11-11 23:25:55 -08:00
init.soso 5886 2020-01-12 21:30:29 -08:00
modrm.pdf 5485 - promote SubX to top-level 2019-07-27 17:47:59 -07:00
mu-init-test.subx 6153 - switch 'main' to use Mu strings 2020-03-15 21:03:12 -07:00
mu-init.subx 7250 2020-11-16 00:00:32 -08:00
mu.dte 6175 - syntax highlighting for dte 2020-03-29 13:25:00 -07:00
mu.md 7691 2021-02-07 09:53:14 -08:00
mu.vim 7785 - baremetal/shell: trace primitives done 2021-02-22 20:23:43 -08:00
mu_instructions 7478 2021-01-03 22:38:41 -08:00
run_one_test 6200 - --dump is not needed for incremental traces 2020-04-09 00:56:32 -07:00
run_one_test.subx 6072 2020-02-29 22:36:03 -08:00
sib.pdf 5485 - promote SubX to top-level 2019-07-27 17:47:59 -07:00
subx.dte 6176 2020-03-29 14:13:03 -07:00
subx.el 5843 2019-12-29 13:40:22 -08:00
subx.gedit 5841 - rudimentary syntax highlighting for gedit 2019-12-28 20:02:45 -08:00
subx.md 6885 - starting on floating-point instructions 2020-09-27 21:12:48 -07:00
subx.nanorc 5840 - syntax highlighting for nano (!!) 2019-12-28 19:16:24 -08:00
subx.vim 6398 2020-05-24 22:47:09 -07:00
subx_bare.md 7439 - start translating Mu programs to baremetal 2020-12-28 11:09:30 -08:00
subx_debugging.md 7401 - clean up support for non-Linux platforms 2020-12-25 12:28:10 -08:00
subx_opcodes 7412 - drawing pixels to screen 2020-12-26 19:13:23 -08:00
test_apps 7448 2020-12-28 20:01:24 -08:00
test_apps_emulated 7448 2020-12-28 20:01:24 -08:00
test_layers 6707 2020-08-02 17:32:01 -07:00
translate_mu 7401 - clean up support for non-Linux platforms 2020-12-25 12:28:10 -08:00
translate_mu_baremetal 7469 - first working baremetal Mu program 2020-12-29 21:08:05 -08:00
translate_mu_baremetal_emulated 7506 2021-01-12 23:04:06 -08:00
translate_mu_debug 7401 - clean up support for non-Linux platforms 2020-12-25 12:28:10 -08:00
translate_mu_emulated 7401 - clean up support for non-Linux platforms 2020-12-25 12:28:10 -08:00
translate_subx 7440 2020-12-28 11:09:31 -08:00
translate_subx_baremetal 7835 2021-03-01 22:41:13 -08:00
translate_subx_baremetal_emulated 7835 2021-03-01 22:41:13 -08:00
translate_subx_debug 7401 - clean up support for non-Linux platforms 2020-12-25 12:28:10 -08:00
translate_subx_emulated 7440 2020-12-28 11:09:31 -08:00
vimrc.vim 7760 2021-02-20 22:37:08 -08:00
vocabulary.md 6658 2020-07-18 15:56:32 -07:00
x86_approx.md 6945 2020-10-04 01:33:49 -07:00

README.md

Mu: a human-scale computer

Mu is a minimal-dependency hobbyist computing stack (everything above the processor).

Mu is not designed to operate in large clusters providing services for millions of people. Mu is designed for you, to run one computer. (Or a few.) Running the code you want to run, and nothing else.

$ git clone https://github.com/akkartik/mu
$ cd mu
$ ./translate_mu apps/ex2.mu  # emit a.elf
$ ./a.elf  # add 3 and 4
$ echo $?
7

Rather than start from some syntax and introduce layers of translation to implement it, Mu starts from the processor's instruction set and tries to get to some safe and clear syntax with as few layers of translation as possible. The emphasis is on internal consistency at any point in time rather than compatibility with the past. (More details.)

Currently Mu requires a 32-bit x86 processor.

Goals

In priority order:

  • Reward curiosity.
  • Safe.
    • Thorough test coverage. If you break something you should immediately see an error message. If you can manually test for something you should be able to write an automated test for it.
    • Memory leaks over memory corruption.
  • Teach the computer bottom-up.

Non-goals

  • Speed. Staying close to machine code should naturally keep Mu fast enough.
  • Efficiency. Controlling the number of abstractions should naturally keep Mu using far less than the gigabytes of memory modern computers have.
  • Portability. Mu will run on any computer as long as it's x86. I will enthusiastically contribute to support for other processors -- in separate forks. Readers shouldn't have to think about processors they don't have.
  • Compatibility. The goal is to get off mainstream stacks, not to perpetuate them. Sometimes the right long-term solution is to bump the major version number.
  • Syntax. Mu code is meant to be comprehended by running, not just reading. For now it's a thin veneer over machine code. I'm working on memory safety before expressive syntax.

Toolchain

The Mu stack consists of:

  • the Mu type-safe language;
  • SubX, an unsafe notation for a subset of x86 machine code; and
  • bare SubX, a more rudimentary form of SubX without certain syntax sugar.

All Mu programs get translated through these layers into tiny zero-dependency binaries that run natively. The translators for most levels are built out of lower levels. The translator from Mu to SubX is written in SubX, and the translator from SubX to bare SubX is built in bare SubX. There is also an emulator for Mu's supported subset of x86, that's useful for debugging SubX programs.

Mu programs build natively either on Linux or on Windows using WSL 2. For Macs and other Unix-like systems, use the emulator:

$ ./translate_mu_emulated apps/ex2.mu  # ~2 mins to emit a.elf
$ ./bootstrap run ./a.elf  # run in the emulator
$ echo $?

Mu programs can be written for two very different environments:

  • With just a Linux kernel. This is the environment that Mu bootstraps itself into, and it's the option for programming with stdin, stdout and file descriptors.

  • Without an OS, by interacting directly with the screen and keyboard. This is the option for rudimentary pixel graphics. There's currently no mouse, no hardware acceleration, no virtual memory, no process separation, no multi-tasking, no persistent storage, no network. These programs have not yet been tested on native hardware, only on on Qemu and Bochs. But these baremetal programs build from scratch, without any reliance on C. This is the future. Here is Conway's Game of Life on Mu:

    $ ./translate_mu_baremetal baremetal/life.mu  # emit disk.img
    $ qemu-system-i386 disk.img
    
    screenshot of Game of Life running on Mu without any intervening Operating System

Use translate_mu to build programs for Linux, and translate_mu_baremetal for running without Linux. The standard libraries are totally separate for the two options, so programs for one won't run on the other.

incomplete tools

There's a prototype live-updating programming environment for a postfix language:

$ ./translate_mu apps/tile/*.mu
$ ./a.elf screen

Once generated, ELF binaries can be packaged up with a Linux kernel into a bootable disk image. Here's how the postfix environment might look on startup:

$ ./translate_mu apps/tile/*.mu  # emit a.elf
# dependencies
$ sudo apt install build-essential flex bison wget libelf-dev libssl-dev xorriso
$ tools/iso/linux a.elf
$ qemu-system-x86_64 -m 256M -cdrom mu_linux.iso -boot d
screenshot of Mu running on Qemu

The disk image also runs on any cloud server that supports custom images.

Mu also runs on the minimal hobbyist OS Soso. (Requires graphics and sudo access. Currently doesn't work on a cloud server.)

$ ./translate_mu apps/ex2.mu  # emit a.elf
# dependencies
$ sudo apt install build-essential util-linux nasm xorriso  # maybe also dosfstools and mtools
$ tools/iso/soso a.elf  # requires sudo
$ qemu-system-i386 -cdrom mu_soso.iso

Syntax

The entire stack shares certain properties and conventions. Programs consist of functions and functions consist of statements, each performing a single operation. Operands to statements are always variables or constants. You can't perform a + b*c in a single statement; you have to break it up into two. Variables can live in memory or in registers. Registers must be explicitly specified. There are some shared lexical rules. Comments always start with '#'. Numbers are always written in hex. Many terms can have context-dependent metadata attached after '/'.

Here's an example program in Mu:

ex2.mu

More details on Mu syntax →

Here's an example program in SubX:

== code
Entry:
  # ebx = 1
  bb/copy-to-ebx  1/imm32
  # increment ebx
  43/increment-ebx
  # exit(ebx)
  e8/call  syscall_exit/disp32

More details on SubX syntax →

Forks

Forks of Mu are encouraged. If you don't like something about this repo, feel free to make a fork. If you show it to me, I'll link to it here. I might even pull your changes into this repo!

  • mu-normie: with a more standard build system that organizes the repo by header files and compilation units. Stays in sync with this repo.
  • mu-x86_64: experimental fork for 64-bit x86 in collaboration with Max Bernstein. It's brought up a few concrete open problems that I don't have good solutions for yet.
  • uCISC: a 16-bit processor being designed from scratch by Robert Butler and programmed with a SubX-like syntax.
  • subv: experimental SubX-like syntax by s-ol bekic for the RISC-V instruction set.

Desiderata

If you're still reading, here are some more things to check out:

Credits

Mu builds on many ideas that have come before, especially:

  • Peter Naur for articulating the paramount problem of programming: communicating a codebase to others;
  • Christopher Alexander and Richard Gabriel for the intellectual tools for reasoning about the higher order design of a codebase;
  • David Parnas and others for highlighting the value of separating concerns and stepwise refinement;
  • The folklore of debugging by print and the trace facility in many Lisp systems;
  • Automated tests for showing the value of developing programs inside an elaborate harness;

On a more tactical level, this project has made progress in a series of bursts as I discovered the following resources. In autobiographical order, with no claims of completeness: