https://github.com/akkartik/mu Skip to content Sign up * Why GitHub? + Features + Mobile + Actions + Codespaces + Packages + Security + Code review + Issues + Integrations + GitHub Sponsors + Customer stories * Team * Enterprise * Explore + Explore GitHub + Learn and contribute + Topics + Collections + Trending + Learning Lab + Open source guides + Connect with others + The ReadME Project + Events + Community forum + GitHub Education + GitHub Stars program * Marketplace * Pricing + Plans + Compare plans + Contact Sales + Education [ ] * # In this repository All GitHub | Jump to | * No suggested jump to results * # In this repository All GitHub | Jump to | * # In this user All GitHub | Jump to | * # In this repository All GitHub | Jump to | Sign in Sign up {{ message }} akkartik / mu Public * Notifications * Star 1.1k * Fork 44 * Soul of a tiny new machine. More thorough tests - More comprehensible and rewrite-friendly software - More resilient society. akkartik.name/akkartik-convivial-20200607.pdf GPL-2.0 License 1.1k stars 44 forks Star Notifications * Code * Issues 2 * Pull requests 1 * Wiki * Security * Insights More * Code * Issues * Pull requests * Wiki * Security * Insights main Switch branches/tags [ ] Branches Tags Could not load branches Nothing to show Loading {{ refName }} default View all branches Could not load tags Nothing to show {{ refName }} default Loading View all tags 16 branches 0 tags Code Loading Latest commit @akkartik akkartik link to the Mu tour ... d46441e Dec 7, 2021 link to the Mu tour d46441e Git stats * 8,982 commits Files Permalink Failed to load latest commit information. Type Name Latest commit message Commit time apps rename grapheme to code-point-utf8 Nov 9, 2021 archive 6206 Apr 17, 2020 browse-slack slack: one more corner case during import Nov 10, 2021 editor rename grapheme to code-point-utf8 Nov 9, 2021 html . Nov 9, 2021 linux keep 'grapheme-stack' Nov 9, 2021 shell rename grapheme to code-point-utf8 Nov 9, 2021 tools . Nov 11, 2021 tutorial . Nov 30, 2021 .gitattributes 6690 Jul 31, 2020 .gitignore create .gitignore Jun 18, 2021 101screen.subx helper to render fonts outside video RAM, take 2 Jun 13, 2021 102keyboard.subx . May 15, 2021 103glyph.subx bugfix: rendering fake screens Oct 12, 2021 104test.subx . Jun 8, 2021 105string-equal.subx 7842 - new directory organization Mar 4, 2021 106stream.subx 7842 - new directory organization Mar 4, 2021 108write.subx periodic run of misc_checks Jun 13, 2021 109stream-equal.subx snapshot Jun 21, 2021 112read-byte.subx . Aug 10, 2021 113write-stream.subx reading from streams Jul 4, 2021 115write-byte.subx support backspace when reading line from keyboard Oct 14, 2021 117write-int-hex.subx 7842 - new directory organization Mar 4, 2021 118parse-hex-int.subx print call stack on all low-level errors May 15, 2021 120allocate.subx debugging helper: heap remaining Aug 11, 2021 121new-stream.subx print call stack on all low-level errors May 15, 2021 123slice.subx print call stack on all low-level errors May 15, 2021 124next-token.subx 7842 - new directory organization Mar 4, 2021 126write-int-decimal.subx rename grapheme to code-point-utf8 Nov 9, 2021 127next-word.subx support non-line-oriented processing in next-word Jul 30, 2021 301array-equal.subx 7842 - new directory organization Mar 4, 2021 302stack_allocate.subx 7254 Nov 17, 2020 308allocate-array.subx 7254 Nov 17, 2020 309stream.subx . Jul 8, 2021 310copy-bytes.subx reading from streams Jul 4, 2021 311decimal-int.subx . May 15, 2021 312copy.subx 7842 - new directory organization Mar 4, 2021 313index-bounds-check.subx start double-buffering May 18, 2021 314divide.subx 7290 Nov 28, 2020 315stack-debug.subx . May 15, 2021 316colors.subx primitive: read r/g/b for color May 2, 2021 317abort.subx fix bad terminology: grapheme -> code point Aug 30, 2021 318debug-counter.subx . Jun 30, 2021 319timer.subx more general timer interface Jun 30, 2021 400.mu rename grapheme to code-point-utf8 Nov 9, 2021 403unicode.mu rename grapheme to code-point-utf8 Nov 9, 2021 408float.mu maintain aspect ratio when rendering images Jul 29, 2021 411string.mu rename grapheme to code-point-utf8 Nov 9, 2021 412render-float-decimal.mu 7842 - new directory organization Mar 4, 2021 500fake-screen.mu rename grapheme to code-point-utf8 Nov 9, 2021 501draw-text.mu rename grapheme to code-point-utf8 Nov 9, 2021 502test.mu . Oct 13, 2021 503manhattan-line.mu 7842 - new directory organization Mar 4, 2021 504test-screen.mu rename grapheme to code-point-utf8 Nov 9, 2021 505colors.mu . Jul 14, 2021 506math.mu press '+' and '-' to zoom in and out respectively May 17, 2021 507line.mu animate transition from sum to filter node May 16, 2021 508circle.mu reimplement Bresenham circle in Mu May 16, 2021 509bezier.mu first bit of animation May 16, 2021 510disk.mu more powerful load-sectors Jul 16, 2021 511image.mu task: juggling function outputs between registers Oct 27, 2021 512array.mu render functions in MRU order Jul 19, 2021 513grapheme-stack.mu . Nov 9, 2021 514gap-buffer.mu keep 'grapheme-stack' Nov 9, 2021 515parse-float.mu parse float from text Oct 13, 2021 516read-line.mu support backspace when reading line from keyboard Oct 14, 2021 LICENSE.txt 7489 - include GNU Unifont Jan 10, 2021 README.md link to the Mu tour Dec 7, 2021 boot.subx start hacky experiment to support combining chars Sep 1, 2021 cheatsheet.pdf 5485 - promote SubX to top-level Jul 28, 2019 font.subx . Oct 10, 2021 help make online help more obvious Apr 5, 2021 misc_checks some hacky checks for common errors Apr 1, 2021 misc_checks.subx some hacky checks for common errors Apr 1, 2021 modrm.pdf 5485 - promote SubX to top-level Jul 28, 2019 mu-init.subx . Jul 20, 2021 mu.md rename grapheme to code-point-utf8 Nov 9, 2021 mu_instructions compute-offset: literal index Aug 26, 2021 sib.pdf 5485 - promote SubX to top-level Jul 28, 2019 signatures.mu keep 'grapheme-stack' Nov 9, 2021 subx.md . Oct 29, 2021 subx_bare.md . Mar 30, 2021 subx_opcodes support checking overflow flag everywhere May 9, 2021 translate start hacky experiment to support combining chars Sep 1, 2021 translate_emulated Mac OS build broken since Aug 29 :/ Oct 31, 2021 vimrc.vim . Aug 8, 2021 vocabulary.md . Nov 9, 2021 View code [ ] Mu: a human-scale computer Goals Non-goals Toolchain Syntax Forks Desiderata Credits 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. Here's the Mu computer running Conway's Game of Life. git clone https://github.com/akkartik/mu cd mu ./translate apps/life.mu # emit a bootable code.img qemu-system-i386 code.img screenshot of Game of Life running on the Mu computer (Colorized sources. This is memory-safe code, and most statements map to a single instruction of machine code.) 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.) Tests are a key mechanism here for creating a computer that others can make their own. I want to encourage a style of active and interactive reading with Mu. If something doesn't make sense, try changing it and see what tests break. Any breaking change should cause a failure in some well-named test somewhere. Currently Mu requires a 32-bit x86 processor. It supports a short list of generic hardware, and can't do networking yet. Goals In priority order: * Reward curiosity. + Easy to build, easy to run. Minimal dependencies, so that installation is always painless. + All design decisions comprehensible to a single individual. (On demand.) + All design decisions comprehensible without needing to talk to anyone. (I always love talking to you, but I try hard to make myself redundant.) + A globally comprehensible codebase rather than locally clean code. + Clear error messages over expressive syntax. * Safe. + Thorough test coverage. If you break something you should immediately see an error message. + Memory leaks over memory corruption. * Teach the computer bottom-up. Thorough test coverage in particular deserves some elaboration. It implies that any manual test should be easy to turn into a reproducible automated test. Mu has some unconventional methods for providing this guarantee. It exposes testable interfaces for hardware using dependency injection so that tests can run on -- and make assertions against -- fake hardware. It also performs automated white-box testing which enables robust tests for performance, concurrency, fault-tolerance, etc. 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. It will always be just a thin memory-safe veneer over machine code. I don't know how to make higher-level notations both fast and comprehensible, so they are likely to remain slow and comprehensible, useful for prototyping but invariably needing to be rewritten in statements that map 1:1 with machine code. The goal of a prototype should be a risk-free rewrite, thanks to tests that capture all the details of lessons learned. Toolchain The Mu stack consists of: * the Mu type-safe and memory-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 (much slower) emulator: ./translate_emulated apps/ex2.mu # 2-5 minutes to emit code.img Mu programs can be written for two very different environments: * At the top-level, Mu programs emit a bootable image that runs without an OS (under emulation; I haven't tested on native hardware yet). There's rudimentary support for some core peripherals: a 1024x768 screen, a keyboard with some key-combinations, a PS/2 mouse that must be polled, a slow ATA disk drive. No hardware acceleration, no virtual memory, no process separation, no multi-tasking, no network. Boot always runs all tests, and only gets to main if all tests pass. * The top-level is built using tools created under the linux/ sub-directory. This sub-directory contains an entirely separate set of libraries intended for building programs that run with just a Linux kernel, reading from stdin and writing to stdout. The Mu compiler is such a program, at linux/mu.subx. Individual programs typically run tests if given a command-line argument called test. The largest program built in Mu today is its prototyping environment for writing slow, interpreted programs in a Lisp-based high-level language. screenshot of the Mu shell (For more details, see the shell/ directory.) While I currently focus on programs without an OS, the linux/ sub-directory is fairly ergonomic. There's a couple of dozen example programs to try out there. It is likely to be the option for a network stack in the foreseeable future; I have no idea how to interact on the network without Linux. 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 resources on Mu: * Mu Syntax reference * Library reference. Mu programs can transparently call low-level functions written in SubX. 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 resources on SubX: * SubX syntax reference * Some starter exercises for learning SubX (labelled hello). Feel free to ping me with any questions. * The list of x86 opcodes supported in SubX: linux/bootstrap/ bootstrap help opcodes. * Some tips for debugging SubX programs. 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 features upstream! * 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. * 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. * mu-normie: with a more standard build system for the linux/ bootstrap/ directory that organizes the repo by header files and compilation units. Stays in sync with this repo. Desiderata If you're still reading, here are some more things to check out: * A slow guided tour of Mu. * How to get your text editor set up for Mu and SubX programs. * Some videos demonstrating Mu programs and features. * A summary of how the Mu compiler translates statements to SubX. Most Mu statements map to a single x86 instruction. (colorized version) * A prototype live-updating programming environment for a postfix language that I might work on again one day: cd linux ./translate tile/*.mu ./a.elf screen * Previous prototypes: mu0, mu1. 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: * "Bootstrapping a compiler from nothing" by Edmund Grimley-Evans. * StoneKnifeForth by Kragen Sitaker, including a tiny sketch of an ELF loader. * "Creating tiny ELF executables" by Brian Raiter. * Single-page cheatsheet for the x86 ISA by Daniel Plohmann (cached local copy) * Minimal Linux Live for teaching how to create a bootable disk image using the syslinux bootloader. * "Writing a bootloader from scratch" by Nick Blundell. * Wikipedia on BIOS interfaces: Int 10h, Int 13h. * Some tips on programming bootloaders by Michael Petch. * xv6, the port of Unix Version 6 to x86 processors * Some tips on handling keyboard interrupts by Alex Dzyoba and Michael Petch. About Soul of a tiny new machine. More thorough tests - More comprehensible and rewrite-friendly software - More resilient society. akkartik.name/akkartik-convivial-20200607.pdf Topics linux programming-literacy white-box-testing unit-tested x86 machine-code Resources Readme License GPL-2.0 License Contributors 8 * @akkartik * @charles-l * @tekknolagi * @an1lam * @sumeet * @KyleAMathews * @jimmyhmiller * @Stich11 Languages * Assembly 70.7% * Forth 22.0% * C++ 6.3% * Shell 0.5% * C 0.3% * Vim Script 0.2% * (c) 2021 GitHub, Inc. * Terms * Privacy * Security * Status * Docs * Contact GitHub * Pricing * API * Training * Blog * About You can't perform that action at this time. You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.