🔀WAT ↔ Binär

Das WebAssembly-Textformat (WAT, Dateiendung .wat) ist die lesbare Form eines Moduls. Es bildet das Binärformat nahezu 1 : 1 ab – jede Befehlszeile wird zu einem Opcode-Byte plus Immediates.

🔗Zuordnung per Hover

Beispiel:

📝 WAT (Textformat)

Das kleinste sinnvolle Modul: zwei i32-Parameter addieren (41 Byte).
1(module
2 (func $add (export "add") (param $a i32) (param $b i32) (result i32)
3 local.get $a
4 local.get $b
5 i32.add))
6

Übersetzt wird mit WABT (wat2wasm, selbst als WebAssembly kompiliert und von dieser Seite ausgeliefert). Die Zeilen-Zuordnung funktioniert für die flache Schreibweise (ein Befehl pro Zeile).

💾 Binär (41 Byte)

0061736d0100000001070160027f7f017f030201000707010361646400000a09010700200020016a0b
Über eine WAT-Zeile oder ein Byte fahren – die Gegenstücke leuchten auf.

🌳Flach oder gefaltet – gleiche Bytes

Flach (Stack-Schreibweise)
local.get $a
local.get $b
i32.add
Gefaltet (S-Ausdruck)
(i32.add
  (local.get $a)
  (local.get $b))
Bytes (beide Varianten)
20 00   local.get 0
20 01   local.get 1
6A      i32.add
✅ Namen sind nur Text
$a und $b werden beim Übersetzen zu Indizes (0, 1). Die Namen landen nur dann im Modul, wenn die optionale Custom Section name geschrieben wird – das Häkchen oben zeigt den Unterschied.

📇Häufige Befehle und ihre Opcodes

Aus der eigenen Opcode-Tabelle (Kern-Spezifikation, Abschnitt Binary Format → Instructions).
20
local.get
Lokale Variable auf den Stack legen
21
local.set
Stack-Wert in lokale Variable schreiben
22
local.tee
Wie local.set, lässt den Wert aber liegen
23
global.get
41
i32.const
Konstante (signed LEB128)
6A
i32.add
Zwei i32 vom Stack nehmen, Summe (mod 2³²) ablegen
6B
i32.sub
a − b (b liegt oben)
6C
i32.mul
Produkt mod 2³²
45
i32.eqz
1, wenn Wert = 0, sonst 0
48
i32.lt_s
a < b (vorzeichenbehaftet) → 1/0
28
i32.load
Liest aus dem linearen Speicher (Adresse vom Stack)
36
i32.store
Schreibt in den linearen Speicher (Adresse, Wert vom Stack)
2D
i32.load8_u
Liest aus dem linearen Speicher (Adresse vom Stack)
3A
i32.store8
Schreibt in den linearen Speicher (Adresse, Wert vom Stack)
02
block
Block – br springt an sein Ende
03
loop
Schleife – br springt an ihren Anfang
04
if
Nimmt i32 vom Stack: ≠ 0 → then-Zweig
05
else
0B
end
Ende eines Blocks bzw. der Funktion
0C
br
Unbedingter Sprung zu Label n
0D
br_if
Springt, wenn i32 vom Stack ≠ 0
10
call
Ruft Funktion mit Index n auf
11
call_indirect
Aufruf über Tabelle, Typ wird zur Laufzeit geprüft
0F
return
1A
drop
Oberstes Stack-Element verwerfen