---------------------------------------------------- Example of some WASM Binary This file breaks down some WASM code, showing the WASM bytecodes and their associated WAST. The idea is to give an idea what the final WASM binary will look like, while remaining readable. ---------------------------------------------------- First, lets start with this example RISC-V code: BackwardBranch: addi t0, zero, 6 subLoop: sub a0, a0, t0 addi t1, zero, 1 bge a0, t1, subLoop beq a0, zero, isMultiple addi a0, zero, -1 isMultiple: addi a0, a0, 1 --- Now, this code becomes the following in WAST: WAST | RISC-V Instruction ------------------------------------------------------------|------------------------------ (i32.const 0) (i32.const 6) (i32.add) (set_local 22) | addi t0, zero, 6 | (loop | (get_local 0) (get_local 22) (i32.sub) (set_local 0) | sub a0, a0, t0 (i32.const 0) (i32.const 1) (i32.add) (set_local 23) | addi t1, zero, 1 | (get_local 0) (get_local 23) (i32.ge_s) | bge a0, t1, subLoop br_if 0 | end) | | (block | (get_local 0) (i32.const 0) (i32.eq) | beq a0, zero, isMultiple br_if 0 | | (i32.const 0) (i32.const -1) (i32.add) (set_local 0) | addi a0, zero, -1 end) | | (get_local 0) (i32.const 1) (i32.add) (set_local 0) | addi a0, a0, 1 | (get_local 0) (return) | Additional bytecodes for returning a0 end | ------------------------------------------------------------------------------------------- When we write out WAST, each instruction, operand, etc has some associated bytecodes that get written to the WASM module. You write these bytecodes in the order they appear, similar to how the RISC-V instructions appear in memory in the order they appear in your code. Unfolding all of the bytecodes, we get the following table that depicts the bytecode equivalent for each part of each instruction: WAST | WASM Bytecodes -----------------|-------------------- i32.const 0 | 0x41 0x00 i32.const 6 | 0x41 0x06 i32.add | 0x6a set_local 22 | 0x21 0x16 loop | 0x03 void | 0x40 (The additional void signature for the start of the loop) get_local 0 | 0x20 0x00 get_local 22 | 0x20 0x16 i32.sub | 0x6b set_local 0 | 0x21 0x00 i32.const 0 | 0x41 0x00 i32.const 1 | 0x41 0x01 i32.add | 0x6a set_local 23 | 0x21 0x17 get_local 0 | 0x20 0x00 get_local 23 | 0x20 0x17 i32.ge_s | 0x4e br_if 0 | 0x0d 0x00 end | 0x0b block | 0x02 void | 0x40 (The additional void signature for the start of the block) get_local 0 | 0x20 0x00 i32.const 0 | 0x41 0x00 i32.eq | 0x46 br_if 0 | 0x0d 0x00 i32.const 0 | 0x41 0x00 i32.const -1 | 0x41 0x7f i32.add | 0x6a set_local 0 | 0x21 0x00 end | 0x0b get_local 0 | 0x20 0x00 i32.const 1 | 0x41 0x01 i32.add | 0x6a set_local 0 | 0x21 0x00 get_local 0 | 0x20 0x00 return | 0x0f end | 0x0b Where the right hand side of the table comprises the entire WASM binary representation of the original RISC-V program.