How x86 emulation works in the browser

From a JavaScript sandbox to a booting PC: what v86 actually does, why it compiles machine code to WebAssembly, and what it cannot do.

A browser tab is a deliberately powerless place. It cannot touch your files, your devices or your memory. So the idea that an operating system could boot inside one sounds like a category error — until you notice that an operating system does not need any of those things. It needs a processor that executes its instructions and hardware that answers when it asks. Both can be written in software.

The emulator

TempMV runs on v86, an emulator of a 32-bit x86 PC. It provides a processor, a memory controller, a PS/2 keyboard and mouse, an IDE disk controller, a floppy controller, a VGA card, a programmable interrupt controller, timers, a real-time clock and a serial port. Together those are enough for a real BIOS to start and a real operating system to boot on top — which is why the systems you can run here are the genuine articles, not reimplementations.

Why not just interpret?

The obvious way to emulate a processor is a loop: read the next instruction, work out what it means, do it, repeat. That works, and it is unbearably slow. Every guest instruction costs dozens of host instructions, most of them spent re-deciding what an instruction you have already seen a million times means.

So v86 does something cleverer. It watches which stretches of guest code actually run, and when a block gets hot it *translates* it — generating a WebAssembly function that does the same thing, handing it to the browser, and letting the browser's own optimising compiler turn it into native code. From then on that block runs at something much closer to full speed. This is just-in-time compilation, with WebAssembly as the target instead of machine code.

Where the disk comes from

The guest thinks it has an IDE disk. In reality, reads are served from a buffer in the page. For a small floppy that buffer is the whole image, downloaded up front. For a 1 GB hard disk that would be absurd, so those images are *streamed*: when the guest asks for a sector, the emulator issues an HTTP range request for exactly the bytes covering it and caches the result. A system that only touches a few hundred megabytes only ever downloads a few hundred megabytes.

Writes go to that same in-memory buffer and are never sent anywhere. That is the whole reason a machine here is temporary: the disk you are modifying is a copy that lives in the tab.

Saving a running machine

Because every part of the machine is data in the page, the entire machine can be serialised: registers, memory, device state, disk contents. That snapshot can be written to a file and restored later, and it is also how the fastest machines in the catalog start — instead of booting, they restore a snapshot someone took *after* the boot finished. See snapshots and machine state.

The limits, plainly

  • 32-bit only. There is no long mode, so no 64-bit operating system will run. This is not a matter of effort; it is not implemented.
  • No hardware virtualisation. Everything is emulated, so expect a fraction of native speed.
  • BIOS, not UEFI, and no TPM. Systems that require modern firmware simply have nothing to boot from.
  • No 3D acceleration. The VGA card is a plain framebuffer.
  • Networking needs a relay. The guest's packets have to be tunnelled over a WebSocket to reach anything, because a tab cannot open raw sockets.

Those constraints are why the catalog looks the way it does. It is not a collection of curiosities because modern systems were left out for taste — it is because a 32-bit BIOS PC is the machine that exists here, and these are the systems that run on it.