Бинарный формат и текстовый WAT

У Wasm два формата — узнаём, зачем и как они переводятся друг в друга.

WAT (WebAssembly Text) — это человекочитаемое текстовое представление того же модуля, что и бинарный .wasm.

Зачем два формата

Браузеру удобно грузить и проверять компактный бинарный файл: он маленький и быстро парсится. Но человеку смотреть в набор байт невозможно. Поэтому стандарт определяет ровно одно и то же содержимое в двух видах: бинарный формат .wasm — для машины, и текстовый формат .wat — для людей. Они полностью эквивалентны: любой .wasm можно превратить в .wat и обратно без потери смысла.

Как выглядит бинарь

Бинарный файл начинается с «магического числа» \0asm и номера версии, затем идут секции: типы функций, импорты, экспорты, тело кода. Если открыть его в hex-редакторе, увидите что-то вроде:

00 61 73 6d   ;; магия: \0 a s m
01 00 00 00   ;; версия 1
...           ;; секции с типами, функциями, экспортами

Тот же модуль в WAT

А вот тот же смысл, но в текстовом WAT — здесь уже всё читается. Это модуль с одной функцией add, которая складывает два целых:

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

WAT построен на s-выражениях — вложенных скобках, как в языке Lisp. Каждая открывающая скобка начинает узел: module, func, param. Это компактно, однозначно разбирается и легко генерируется инструментами.

Как одно превращается в другое

Между форматами переводят утилиты из набора WABT (WebAssembly Binary Toolkit): wat2wasm компилирует текст в бинарь, wasm2wat делает обратное — дизассемблирует бинарь в читаемый текст. Это значит, что любой .wasm, даже скачанный из интернета, можно изучить глазами.

wat2wasm add.wat -o add.wasm   # текст -> бинарь
wasm2wat add.wasm -o back.wat  # бинарь -> текст

Как работает под капотом

WAT — это не «ещё один формат исполнения». Браузер не исполняет текст. WAT всегда сначала компилируется в бинарь (например, через wat2wasm или встроенный в инструменты ассемблер), и уже бинарь грузится в движок. Думайте о WAT как об ассемблере для Wasm: удобная для чтения и записи форма, но шаг компиляции в байты обязателен.

Частые ошибки в понимании

  • «WAT медленнее, чем .wasm» — формат исполнения один и тот же (бинарь). WAT — лишь представление, его всё равно компилируют в байты.
  • «s-выражения — это Lisp» — синтаксис похож, но это просто скобочная запись дерева, никакого Lisp-исполнения нет.
  • «Скачанный .wasm нельзя прочитать» — можно: wasm2wat восстановит читаемый текст (хотя имена локальных переменных могут потеряться).

Итоги

  • У Wasm два эквивалентных формата: бинарный .wasm и текстовый .wat.
  • WAT построен на s-выражениях — вложенных скобках.
  • WABT-утилиты wat2wasm/wasm2wat переводят между ними.
  • Браузер всегда исполняет бинарь; WAT — это удобная для людей форма.
Проверьте себя
1. В каком отношении находятся форматы .wasm и .wat?
A.wat быстрее исполняется
BЭто два эквивалентных представления одного модуля: бинарь для машины, текст для человека
C.wasm — это устаревший формат
D.wat исполняется напрямую браузером
2. На чём построен синтаксис WAT?
AНа отступах, как в Python
BНа s-выражениях — вложенных скобках
CНа фигурных скобках, как в C
DНа XML-тегах
3. Какая утилита превращает .wasm обратно в читаемый текст?
Awat2wasm
Bwasm2wat
Cwasmtime
Demcc