Wasm: A technical view
WebAssembly is one of the most recent technologies of the web and stands for itself in the browser. Historically it is an successor of asm.js.
When supported, code which is written in C, C++, Rust or any other language can be compiled into Wasm bytecode (= .wasm file) and loaded into the JS page and executed in there (source):
const importObject = { imports: { imported_func: (arg) => console.log(arg) } };
WebAssembly.instantiateStreaming(fetch("simple.wasm"), importObject).then(
(obj) => obj.instance.exports.exported_func()
);
The execution happens inside an own runtime. Currently every major browser supports Wasm.
The following is a technical deep-dive into Wasm. If you just want to compile to and use Wasm modules, this knowledge is probably too deep. But it’s always helpful and interesting to understand the inner workings.
Wasm bytecode
The Wasm module itself is encoded in bytecode, which you can inspect with tools like hexdump:
0000000 6100 6d73 0001 0000 0d01 6002 7f04 7f7f
0000010 017f 607f 7f01 0200 0123 7716 7361 5f69
0000020 6e73 7061 6873 746f 705f 6572 6976 7765
0000030 0831 6466 775f 6972 6574 0000 0203 0101
0000040 0305 0001 0701 0212 6d06 6d65 726f 0279
0000050 0500 6568 6c6c 006f 0a01 0110 000e 0020
0000060 c241 4100 410e 1000 1a00 0b0b 0115 4100
0000070 00c2 0e0b 6548 6c6c 2c6f 5720 726f 646c
These are the core sell arguments of Wasm:
- Executing other code bases in the browser (no rewrites in JS needed).
- Running modules in native speed.
You can find the byte code in the specification or also in the op code table.
Writing .wat files
You don’t need to write Rust code and compile it to Wasm to achieve your goal.
In fact, you can also write files in the WebAssembly Text Format or short: WAT.
When you want to write .wat files, then it’s recommended to install at least the WebAssembly Binary Toolkit (wabt).
This are .wat files, which represent Wasm in textual formats.
These files contain S-Expressions that contain the Wasm instructions. You can compile it with wat2wasm to Wasm:
(module
(func $add (param $lhs i32) (param $rhs i32) (result i32)
local.get $lhs
local.get $rhs
i32.add)
(export "add" (func $add))
)
Store this file as main.wat and compile it with wat2wasm main.wat to get a .wasm file.
The stack machine
Although the runtimes make something more efficient out of it, the instructions behave like a stack machine. So, to write code for WebAssembly, you need to think of the instructions in the way of a stack machine!
How it really behaves in the runtime is more an implementation detail and not part of the specification.
The code from above is displayed here again and shows the current state of the stack after the instruction:
(module
(func $add (param $lhs i32) (param $rhs i32) (result i32)
local.get $lhs ;; stack: [$lhs]
local.get $rhs ;; stack: [$lhs, $rhs]
i32.add) ;; stack: [$lhs + $rhs]
(export "add" (func $add))
)
Type checking
Pretty important to know: Wasm has types. These are checked during validation, instantiation and execution.
So when you have a function that expects an i32 type, it expects to get a value of this type.
Wasm runtimes
Beside of the browser, you are also able to run Wasm locally on a machine. There are many(!) runtimes. One of them is wasmtime by the ByteCodeAlliance.
With that runtimes Wasm also aims to make a point toward local machines and execute system commands. To achieve this, the WebAssembly System Interface has been created. This defines a sandbox for the execution of foreign Wasm modules and interfaces for the access of the filesystem as an example.
Where to go from here
That’s just the overfly of the concepts of Wasm and its runtimes. In the next few weeks there’ll be more posts on Wasm. Especially to understand its specification and how to write own WAT files.
Further resources
There are a lot of resources for Wasm. I’d recommend this ones for further reading. Some of this blogs are by Wasm/WASI contributors:
- Wasm by example
- Code cartoons by Lin Clark
- radu’s blog
- sunfishcode’s blog
- Blog by Nick Fitzgerald
- Bringing the web up to speed with WebAssembly is a paper that describes the motivation and origin behind WebAssembly.
- WebAssembly to let developers combine languages flies over Wasm and can be viewed as an addition to this post.