← Back to Lessons Lesson 27 of 28
Advanced getting-started
Wasm Binary Format
The .wasm Binary
Every .wasm file starts with 8 bytes:
00 61 73 6D ← Magic number: "\0asm"
01 00 00 00 ← Version: 1After the header, the file contains sections — each section has a type ID, size, and content.
Sections
| ID | Name | Contains |
|---|---|---|
| 0 | Custom | Debug info, names, metadata |
| 1 | Type | Function type signatures (i32, i32) -> i32 |
| 2 | Import | Functions/memory/globals imported from JS |
| 3 | Function | Maps function index → type signature |
| 4 | Table | Indirect function call tables |
| 5 | Memory | Linear memory declarations (initial + max pages) |
| 6 | Global | Global variable declarations |
| 7 | Export | Functions/memory exposed to JavaScript |
| 8 | Start | Function to call on instantiation |
| 9 | Element | Table initialization data |
| 10 | Code | The actual function bytecode |
| 11 | Data | Static data (strings, constants) |
WAT: The Text Format
WAT (WebAssembly Text) is the human-readable form of Wasm. You can convert between them:
# Binary → text
wasm2wat my_module.wasm -o my_module.wat
# Text → binary
wat2wasm my_module.wat -o my_module.wasmA simple function in WAT
(module
;; Type section: function signature
(type $add_type (func (param i32 i32) (result i32)))
;; Function section + Code section
(func $add (type $add_type) (param $a i32) (param $b i32) (result i32)
local.get $a
local.get $b
i32.add
)
;; Export section
(export "add" (func $add))
)This compiles to the same thing as:
#[wasm_bindgen]
pub fn add(a: i32, b: i32) -> i32 {
a + b
}Wasm Instruction Set
Wasm uses a stack machine — instructions push/pop values on a stack:
;; Calculate (a + b) * 2
local.get $a ;; stack: [a]
local.get $b ;; stack: [a, b]
i32.add ;; stack: [a+b]
i32.const 2 ;; stack: [a+b, 2]
i32.mul ;; stack: [(a+b)*2]Common instructions
| Instruction | What it does |
|---|---|
local.get $x |
Push local variable |
local.set $x |
Pop and store to local |
i32.const N |
Push constant |
i32.add |
Pop 2, push sum |
i32.mul |
Pop 2, push product |
i32.lt_s |
Pop 2, push 1 if less |
if...else...end |
Conditional |
loop...br_if...end |
Loop with conditional break |
call $fn |
Call function |
return |
Return from function |
How the Browser Loads Wasm
// Step 1: Fetch the binary
const response = await fetch('module.wasm');
// Step 2: Compile (streaming = compiles while downloading)
const module = await WebAssembly.compileStreaming(response);
// Step 3: Instantiate (link imports, allocate memory)
const instance = await WebAssembly.instantiate(module, {
env: {
log: (ptr, len) => { /* JS function imported by Wasm */ }
}
});
// Step 4: Call exported functions
const result = instance.exports.add(2, 3);Streaming compilation
Download: ████████████████████░░░░░
Compile: ░░░████████████████████░░
Execute: ░░░░░░░░░░░░░░░░░░░░░░██The browser compiles Wasm while downloading — so a 100KB Wasm file might be ready to execute immediately after the download finishes.
Inspecting .wasm Files
# See what's exported
wasm-objdump -x module.wasm
# See the disassembly
wasm-objdump -d module.wasm
# See section sizes
wasm-objdump -h module.wasm
# Convert to readable text
wasm2wat module.wasmTry It
Click Run to see the binary format structure — magic bytes, version, and all section types that make up a .wasm file.
Try It
Chapter Quiz
Pass all questions to complete this lesson