Hey everyone. I’m a bit obsessed with web assembly, so I thought i’d tried to write some semi-higher quality information about what I’ve learned. Some months ago I just started reading the web assembly spec and poking around at bytes. It all started as just a fundamental question “what’s even in here?” What makes the magic of all this “faster than JavaScript” stuff work? It ended up being pretty fascinating, and several mad science projects later, I found myself recently with a desire to make a web assembly interpreter. Let’s learn as we go!

One of the neat things about web assembly is that the structure of everything inside is fairly human comprehensible. We need a way of representing:

functions

details about our memory

globals

blobs of data (like constant strings of characters like “hello world!”)

names of things we’d like exported

And each one of these major components have their own little section at the binary level. Each section in order has

a type ID number that says what type the section is

how much data is in the section (so you can hop to the next section after)

The first job of our interpreter is really going to just be able take those sections and turn them into enough representation for us to evaluate.

For this first part of a web assembly interpreter, we’re just going to be focused on taking a web assembly program “simple.wasm” that exposes a single function “main” that returns a number.

#[no_mangle]

pub fn main(_args:usize,_len:usize) -> usize {

return 42;

}

To make things more interesting we will be writing our web assembly interpreter in web assembly. We’ll be using the Rust programming language.

How to get our program bytes into our interpreter

Let’s first ask ourselves how we are even going our web assembly program “simple.wasm” into our interpreter. Since all browser applications start in JavaScript, we must look at how JavaScript loads web assembly.