Introduction to WebAssembly Text

June 24, 2021

WebAssembly Text (a.k.a. WAT, a.k.a. Raw Wasm) is like an Assembly language for WebAssembly. WebAssembly is a binary format. WAT instructions correspond to a binary opcode in WebAssembly. If you would like to understand what is going on with WebAssembly, how it works, and how to make the most of it, it is beneficial to know WAT. One thing to note about WebAssembly is that it is a Stack Machine. Instead of using registers, WebAssembly pushes values onto and pops values off of a virtual stack. The choice of a stack machine implementation creates smaller file download sizes.

WAT Code

WAT code looks somewhere about halfway between an Assembly language and a high-level language like JavaScript. In JavaScript, if you had three variable A, B, and C and you wanted to add the values in A and B then store the result in C, you would need a line of code that looks like this:

  C = A + B;

In WAT, your code would look something like this if:

  local.get $a
  local.get $b
  local.set $c

This makes the assumption that the variables $a, $b and $c are all local. Otherwise you would be using global.get and global.set. WAT also has a requirement that all variable names must begin with a dollar sign ($). The local.get statement takes the value in the local variable $a and pushes it onto the stack.

What WAT does well

WAT is a lot more limited than most Assembly languages. WAT is not capable of directly performing any input or output. It can not directly manipulate the DOM in a web browser. WebAssembly can make changes to linear memory and make calls to JavaScript functions passed to the module on initialization. Because the calls to JavaScript come with an additional performance cost, you should do your best to limit the number of Wasm -> Javascritpt.

Writing your first WAT module

Let’s write a quick Wasm module in WAT, and we will call it from JavaScript. This module will take two numbers from JavaScript, add them together, and return the sum. It’s not too exciting but is a good first step towards a larger world of coding WebAssembly Text. You’ll need to have Node.js installed to compile your WAT code into a Wasm binary module. We will use the wat2wasm assembler I created as a part of the wat-wasm npm package. You can install it with the following npm command:

  npm i wat-wasm -g

Once you have installed wat-wasm, you will be able to compile a Wasm module. Create a file named add.wat and add the following code to it:

    (func (export "sum")
      (param $a i32)
      (param $b i32)
      (result i32)
      local.get $a
      local.get $b

Modules in Wasm are defined by the code inside the (module) expression. The module above has a single function sum that I defined for external use using the (export "sum"). This function takes two 32-bit integer parameters $a and $b. It uses the local.get command to load those parameters onto the stack. Then it calls i32.add which pops two 32-bit integers off of the stack, adds them together and pushes the resulting value back onto the stack. The function was defined with a (result i32) expression, so it is expecting a 32-bit integer to be on the stack when the function is complete. This value is what will be returned to the calling function, which in this case will be defined in the JavaScript.

We can compile the module above with the following command:

  wat2wasm add.wat -o add.wasm

Calling a Wasm module from JavaScript

Now we can set up a JavaScript module that calls the Wasm sum function in the Wasm module. Create a file called add.js and add the following code to it:

  const fs = require('fs');
  const bytes = fs.readFileSync(__dirname + "/add.wasm");

  (async () => {
    const obj = await WebAssembly.instantiate(new Uint8Array(bytes));
    let value = obj.instance.exports.sum(7, 5);
    console.log('7 + 5=' + value);

If you run add.js using node, you should see the following output:

  7 + 5=12

The Art of WebAssembly

The Art of WebAssembly
Author and expert Rick Battagline eases the reader through Wasm's complexities using clear explanations, illustrations, & plenty of examples.
Learn More

Hands-On Game Development with WebAssembly

Hands-On Game Dev with Wasm
Author and expert Rick Battagline teaches 2D game development fundamentals in C++ using the Emscripten WebAssembly toolchain.
Learn More

Classic Solitaire
Are you bored right now? Play Classic Solitaire and be slightly less bored. Also, it's how I earn a living, so it would really help me out if you wasted time on my site. :-)
Play Solitaire