Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

附录A 常用 WAT 指令参考

本附录提供 WebAssembly 文本格式 (WAT) 的完整指令参考,按功能分类整理,便于开发时快速查阅。

A.1 模块结构语法

A.1.1 模块定义

(module
  ;; 类型定义
  (type $func_type (func (param i32) (result i32)))
  
  ;; 导入声明
  (import "env" "memory" (memory 1))
  (import "console" "log" (func $log (param i32)))
  
  ;; 函数定义
  (func $name (param $p1 i32) (result i32) ...)
  
  ;; 表定义
  (table $table 10 funcref)
  
  ;; 内存定义
  (memory 1 2)
  
  ;; 全局变量
  (global $counter (mut i32) (i32.const 0))
  
  ;; 导出声明
  (export "function_name" (func $name))
  (export "memory" (memory 0))
  
  ;; 起始函数
  (start $init)
  
  ;; 元素段(初始化表)
  (elem (i32.const 0) $func1 $func2)
  
  ;; 数据段(初始化内存)
  (data (i32.const 0) "Hello World"))

A.1.2 函数定义语法

;; 完整形式
(func $name (param $arg1 i32) (param $arg2 f32) (result i64)
  (local $temp i32)
  ;; 函数体
  local.get $arg1
  i64.extend_i32_s)

;; 简化形式
(func $name (param i32 f32) (result i64)
  ;; 使用索引访问参数:local.get 0, local.get 1
  local.get 0
  i64.extend_i32_s)

;; 多返回值(WebAssembly 2.0+)
(func $swap (param i32 i32) (result i32 i32)
  local.get 1
  local.get 0)

A.2 数据类型和常量

A.2.1 基本数据类型

类型描述大小取值范围
i3232位有符号整数4字节-2³¹ ~ 2³¹-1
i6464位有符号整数8字节-2⁶³ ~ 2⁶³-1
f3232位浮点数4字节IEEE 754 单精度
f6464位浮点数8字节IEEE 754 双精度
v128128位向量16字节SIMD 向量类型
funcref函数引用-函数表中的引用
externref外部引用-宿主环境对象引用

A.2.2 常量定义

;; 整数常量
i32.const 42              ;; 十进制
i32.const 0x2A            ;; 十六进制
i32.const 0o52            ;; 八进制
i32.const 0b101010        ;; 二进制
i32.const -123            ;; 负数

i64.const 1234567890123456789
i64.const 0x112210F47DE98115

;; 浮点数常量
f32.const 3.14159         ;; 标准形式
f32.const 1.23e-4         ;; 科学记数法
f32.const 0x1.921FB6p+1   ;; 十六进制浮点数
f32.const inf             ;; 正无穷
f32.const -inf            ;; 负无穷
f32.const nan             ;; NaN
f32.const nan:0x400000    ;; 带载荷的 NaN

f64.const 2.718281828459045
f64.const 0x1.5BF0A8B145769p+1

A.3 算术指令

A.3.1 整数算术指令

基本算术运算

;; i32 算术指令
i32.add         ;; 加法:a + b
i32.sub         ;; 减法:a - b  
i32.mul         ;; 乘法:a * b
i32.div_s       ;; 有符号除法:a / b
i32.div_u       ;; 无符号除法:a / b
i32.rem_s       ;; 有符号取余:a % b
i32.rem_u       ;; 无符号取余:a % b

;; i64 算术指令(同 i32)
i64.add         i64.sub         i64.mul
i64.div_s       i64.div_u
i64.rem_s       i64.rem_u

;; 一元运算
i32.clz         ;; 前导零计数
i32.ctz         ;; 后导零计数
i32.popcnt      ;; 位计数(汉明重量)
i32.eqz         ;; 等于零测试 (i32 → i32)

i64.clz         i64.ctz         i64.popcnt      i64.eqz

位运算指令

;; 按位逻辑运算
i32.and         ;; 按位与:a & b
i32.or          ;; 按位或:a | b
i32.xor         ;; 按位异或:a ^ b

;; 移位运算
i32.shl         ;; 左移:a << b
i32.shr_s       ;; 算术右移:a >> b (保持符号)
i32.shr_u       ;; 逻辑右移:a >>> b (补零)
i32.rotl        ;; 循环左移
i32.rotr        ;; 循环右移

;; i64 位运算(同 i32)
i64.and         i64.or          i64.xor
i64.shl         i64.shr_s       i64.shr_u
i64.rotl        i64.rotr

A.3.2 浮点算术指令

;; f32/f64 基本算术
f32.add         f64.add         ;; 加法
f32.sub         f64.sub         ;; 减法
f32.mul         f64.mul         ;; 乘法
f32.div         f64.div         ;; 除法

;; 数学函数
f32.abs         f64.abs         ;; 绝对值
f32.neg         f64.neg         ;; 取负
f32.ceil        f64.ceil        ;; 向上取整
f32.floor       f64.floor       ;; 向下取整
f32.trunc       f64.trunc       ;; 截断取整
f32.nearest     f64.nearest     ;; 四舍五入到最近整数
f32.sqrt        f64.sqrt        ;; 平方根

;; 最值运算
f32.min         f64.min         ;; 最小值
f32.max         f64.max         ;; 最大值
f32.copysign    f64.copysign    ;; 复制符号位

A.4 比较指令

A.4.1 整数比较

;; i32 比较指令(返回 i32:1 为真,0 为假)
i32.eq          ;; 相等:a == b
i32.ne          ;; 不等:a != b
i32.lt_s        ;; 有符号小于:a < b
i32.lt_u        ;; 无符号小于:a < b
i32.gt_s        ;; 有符号大于:a > b
i32.gt_u        ;; 无符号大于:a > b
i32.le_s        ;; 有符号小于等于:a <= b
i32.le_u        ;; 无符号小于等于:a <= b
i32.ge_s        ;; 有符号大于等于:a >= b
i32.ge_u        ;; 无符号大于等于:a >= b

;; i64 比较指令(同 i32)
i64.eq          i64.ne
i64.lt_s        i64.lt_u        i64.gt_s        i64.gt_u
i64.le_s        i64.le_u        i64.ge_s        i64.ge_u

A.4.2 浮点比较

;; f32/f64 比较指令(返回 i32)
f32.eq          f64.eq          ;; 相等
f32.ne          f64.ne          ;; 不等
f32.lt          f64.lt          ;; 小于
f32.gt          f64.gt          ;; 大于
f32.le          f64.le          ;; 小于等于
f32.ge          f64.ge          ;; 大于等于

A.5 类型转换指令

A.5.1 整数类型转换

;; 扩展和截断
i64.extend_i32_s        ;; i32 → i64 (有符号扩展)
i64.extend_i32_u        ;; i32 → i64 (无符号扩展)
i32.wrap_i64            ;; i64 → i32 (截断低32位)

;; 截断扩展(符号扩展)
i32.extend8_s           ;; i8 → i32 (有符号扩展)
i32.extend16_s          ;; i16 → i32 (有符号扩展)
i64.extend8_s           ;; i8 → i64 (有符号扩展)
i64.extend16_s          ;; i16 → i64 (有符号扩展)
i64.extend32_s          ;; i32 → i64 (有符号扩展)

A.5.2 浮点类型转换

;; 浮点精度转换
f64.promote_f32         ;; f32 → f64 (提升精度)
f32.demote_f64          ;; f64 → f32 (降低精度)

;; 整数与浮点数转换
f32.convert_i32_s       ;; i32 → f32 (有符号)
f32.convert_i32_u       ;; i32 → f32 (无符号)
f32.convert_i64_s       ;; i64 → f32 (有符号)
f32.convert_i64_u       ;; i64 → f32 (无符号)
f64.convert_i32_s       ;; i32 → f64 (有符号)
f64.convert_i32_u       ;; i32 → f64 (无符号)
f64.convert_i64_s       ;; i64 → f64 (有符号)
f64.convert_i64_u       ;; i64 → f64 (无符号)

;; 浮点数到整数转换
i32.trunc_f32_s         ;; f32 → i32 (有符号截断)
i32.trunc_f32_u         ;; f32 → i32 (无符号截断)
i32.trunc_f64_s         ;; f64 → i32 (有符号截断)
i32.trunc_f64_u         ;; f64 → i32 (无符号截断)
i64.trunc_f32_s         ;; f32 → i64 (有符号截断)
i64.trunc_f32_u         ;; f32 → i64 (无符号截断)
i64.trunc_f64_s         ;; f64 → i64 (有符号截断)
i64.trunc_f64_u         ;; f64 → i64 (无符号截断)

;; 饱和截断(避免溢出异常)
i32.trunc_sat_f32_s     ;; f32 → i32 (有符号饱和)
i32.trunc_sat_f32_u     ;; f32 → i32 (无符号饱和)
i32.trunc_sat_f64_s     ;; f64 → i32 (有符号饱和)
i32.trunc_sat_f64_u     ;; f64 → i32 (无符号饱和)
i64.trunc_sat_f32_s     ;; f32 → i64 (有符号饱和)
i64.trunc_sat_f32_u     ;; f32 → i64 (无符号饱和)
i64.trunc_sat_f64_s     ;; f64 → i64 (有符号饱和)
i64.trunc_sat_f64_u     ;; f64 → i64 (无符号饱和)

A.5.3 重新解释类型

;; 位模式重新解释(不改变位表示)
i32.reinterpret_f32     ;; f32 → i32 (位模式转换)
i64.reinterpret_f64     ;; f64 → i64 (位模式转换)
f32.reinterpret_i32     ;; i32 → f32 (位模式转换)
f64.reinterpret_i64     ;; i64 → f64 (位模式转换)

A.6 局部变量和栈操作

A.6.1 局部变量操作

;; 获取局部变量/参数
local.get $name         ;; 按名称获取
local.get 0             ;; 按索引获取(0是第一个参数)

;; 设置局部变量
local.set $name         ;; 按名称设置
local.set 0             ;; 按索引设置

;; 设置并获取局部变量
local.tee $name         ;; 设置变量并保留栈顶值
local.tee 0             ;; 按索引操作

A.6.2 全局变量操作

;; 获取全局变量
global.get $name        ;; 按名称获取
global.get 0            ;; 按索引获取

;; 设置全局变量(仅限可变全局变量)
global.set $name        ;; 按名称设置
global.set 0            ;; 按索引设置

A.6.3 栈操作指令

drop                    ;; 丢弃栈顶值
select                  ;; 条件选择:condition ? a : b
                        ;; 栈:[condition] [false_val] [true_val] → [result]

A.7 控制流指令

A.7.1 基本控制结构

;; 无条件块
(block $label
  ;; 代码块
  br $label)            ;; 跳出块

;; 循环块
(loop $label
  ;; 循环体
  br $label)            ;; 跳回循环开始

;; 条件分支
(if (result i32)        ;; 可选返回类型
  ;; 条件表达式
  (then
    ;; then 分支)
  (else
    ;; else 分支))        ;; else 分支可选

A.7.2 跳转指令

br $label               ;; 无条件跳转到标签
br_if $label            ;; 条件跳转:如果栈顶非零则跳转
br_table $l1 $l2 $default   ;; 表跳转(switch 语句)
return                  ;; 函数返回
unreachable             ;; 标记不可达代码(触发 trap)

A.7.3 函数调用

call $function_name     ;; 直接函数调用
call_indirect (type $sig) $table   ;; 间接函数调用(通过函数表)

A.8 内存操作指令

A.8.1 内存加载指令

;; 基本加载指令
i32.load                ;; 加载32位整数
i64.load                ;; 加载64位整数  
f32.load                ;; 加载32位浮点数
f64.load                ;; 加载64位浮点数

;; 带偏移和对齐的加载
i32.load offset=4 align=4
i64.load offset=8 align=8

;; 部分加载(扩展)
i32.load8_s             ;; 加载8位有符号扩展到32位
i32.load8_u             ;; 加载8位无符号扩展到32位
i32.load16_s            ;; 加载16位有符号扩展到32位
i32.load16_u            ;; 加载16位无符号扩展到32位
i64.load8_s             ;; 加载8位有符号扩展到64位
i64.load8_u             ;; 加载8位无符号扩展到64位
i64.load16_s            ;; 加载16位有符号扩展到64位
i64.load16_u            ;; 加载16位无符号扩展到64位
i64.load32_s            ;; 加载32位有符号扩展到64位
i64.load32_u            ;; 加载32位无符号扩展到64位

A.8.2 内存存储指令

;; 基本存储指令
i32.store               ;; 存储32位整数
i64.store               ;; 存储64位整数
f32.store               ;; 存储32位浮点数
f64.store               ;; 存储64位浮点数

;; 带偏移和对齐的存储
i32.store offset=4 align=4
i64.store offset=8 align=8

;; 部分存储(截断)
i32.store8              ;; 存储32位整数的低8位
i32.store16             ;; 存储32位整数的低16位
i64.store8              ;; 存储64位整数的低8位
i64.store16             ;; 存储64位整数的低16位
i64.store32             ;; 存储64位整数的低32位

A.8.3 内存管理指令

memory.size             ;; 获取内存大小(以页为单位,1页=64KB)
memory.grow             ;; 增长内存大小,返回之前的大小

;; 批量内存操作(bulk memory operations)
memory.init $data_segment    ;; 从数据段初始化内存
data.drop $data_segment      ;; 丢弃数据段
memory.copy                  ;; 复制内存区域  
memory.fill                  ;; 填充内存区域

A.9 表操作指令

A.9.1 基本表操作

table.get $table        ;; 获取表元素
table.set $table        ;; 设置表元素
table.size $table       ;; 获取表大小
table.grow $table       ;; 增长表大小
table.fill $table       ;; 填充表
table.copy $dest $src   ;; 复制表元素
table.init $table $elem ;; 从元素段初始化表
elem.drop $elem         ;; 丢弃元素段

A.10 原子操作指令(线程扩展)

A.10.1 原子内存操作

;; 原子加载/存储
i32.atomic.load         ;; 原子加载32位
i64.atomic.load         ;; 原子加载64位
i32.atomic.store        ;; 原子存储32位
i64.atomic.store        ;; 原子存储64位

;; 读-修改-写操作
i32.atomic.rmw.add      ;; 原子加法
i32.atomic.rmw.sub      ;; 原子减法
i32.atomic.rmw.and      ;; 原子与运算
i32.atomic.rmw.or       ;; 原子或运算
i32.atomic.rmw.xor      ;; 原子异或运算
i32.atomic.rmw.xchg     ;; 原子交换

;; 比较并交换
i32.atomic.rmw.cmpxchg  ;; 原子比较并交换

;; 内存屏障
memory.atomic.notify    ;; 通知等待线程
memory.atomic.wait32    ;; 等待32位值变化
memory.atomic.wait64    ;; 等待64位值变化
atomic.fence            ;; 内存屏障

A.11 SIMD 指令(向量扩展)

A.11.1 向量操作

;; v128 类型常量
v128.const i32x4 1 2 3 4        ;; 创建4个i32向量
v128.const f32x4 1.0 2.0 3.0 4.0 ;; 创建4个f32向量

;; 向量加载/存储
v128.load                       ;; 加载128位向量
v128.load8x8_s                  ;; 加载8个i8,扩展到i16
v128.load16x4_s                 ;; 加载4个i16,扩展到i32
v128.load32x2_s                 ;; 加载2个i32,扩展到i64
v128.store                      ;; 存储128位向量

;; 向量算术运算
i32x4.add                       ;; 4个i32并行加法
i32x4.sub                       ;; 4个i32并行减法
i32x4.mul                       ;; 4个i32并行乘法
f32x4.add                       ;; 4个f32并行加法
f32x4.sqrt                      ;; 4个f32并行平方根

;; 向量比较
i32x4.eq                        ;; 4个i32并行相等比较
f32x4.lt                        ;; 4个f32并行小于比较

;; 向量选择和混合
v128.bitselect                  ;; 按位选择
i8x16.shuffle                   ;; 字节shuffle重排

A.12 异常处理指令(异常扩展)

A.12.1 异常操作

;; 异常标签定义
(tag $my_exception (param i32))

;; 异常处理块
(try (result i32)
  ;; 可能抛出异常的代码
  (throw $my_exception (i32.const 42))
  (catch $my_exception
    ;; 异常处理代码
    drop    ;; 丢弃异常参数
    i32.const -1))

;; 异常指令
throw $tag                      ;; 抛出异常
rethrow $label                  ;; 重新抛出异常

A.13 常用代码模式

A.13.1 条件表达式模式

;; 三元运算符模式
(if (result i32)
  ;; 条件
  (then ;; 真值)
  (else ;; 假值))

;; 使用 select 的简化版本
(select
  ;; 真值
  ;; 假值
  ;; 条件)

A.13.2 循环模式

;; 计数循环
(local $i i32)
(local.set $i (i32.const 0))
(loop $loop
  ;; 循环体
  
  ;; 递增计数器
  (local.set $i (i32.add (local.get $i) (i32.const 1)))
  
  ;; 条件检查
  (br_if $loop (i32.lt_s (local.get $i) (i32.const 10))))

;; while 循环模式
(loop $while
  (if (;; 条件)
    (then
      ;; 循环体
      (br $while))))

;; do-while 循环模式
(loop $do_while
  ;; 循环体
  
  (br_if $do_while (;; 条件)))

A.13.3 函数指针和回调模式

;; 定义函数类型
(type $callback (func (param i32) (result i32)))

;; 函数表
(table $callbacks 10 funcref)

;; 回调调用
(func $call_callback (param $index i32) (param $value i32) (result i32)
  (call_indirect (type $callback)
    (local.get $value)
    (local.get $index)))

A.13.4 错误处理模式

;; 返回错误码
(func $safe_divide (param $a i32) (param $b i32) (result i32)
  (if (result i32)
    (i32.eqz (local.get $b))
    (then (i32.const -1))  ;; 错误码
    (else (i32.div_s (local.get $a) (local.get $b)))))

;; 使用全局错误标志
(global $error_flag (mut i32) (i32.const 0))

(func $operation_with_error_flag
  ;; 重置错误标志
  (global.set $error_flag (i32.const 0))
  
  ;; 操作...
  ;; 如果出错
  (global.set $error_flag (i32.const 1)))

A.14 性能优化提示

A.14.1 指令选择优化

;; 优先使用高效指令
;; 好:使用移位代替乘法/除法(当可能时)
(i32.shl (local.get $x) (i32.const 3))  ;; x * 8

;; 避免:
(i32.mul (local.get $x) (i32.const 8))

;; 好:使用位运算检查奇偶
(i32.and (local.get $x) (i32.const 1))  ;; x % 2

;; 避免:
(i32.rem_s (local.get $x) (i32.const 2))

A.14.2 内存访问优化

;; 好:按对齐边界访问
i32.load align=4        ;; 4字节对齐
i64.load align=8        ;; 8字节对齐

;; 避免:未对齐访问
i32.load align=1        ;; 可能较慢

;; 好:批量操作
memory.copy             ;; 比循环复制更快
memory.fill             ;; 比循环填充更快

A.14.3 控制流优化

;; 好:减少跳转
(if (local.get $condition)
  (then
    ;; 直接计算))

;; 避免:过多嵌套
(if (local.get $a)
  (then
    (if (local.get $b)
      (then
        (if (local.get $c)
          ;; 过度嵌套)))))

A.15 调试和开发技巧

A.15.1 调试辅助模式

;; 使用 unreachable 标记错误路径
(if (i32.lt_s (local.get $index) (i32.const 0))
  (then
    unreachable))  ;; 触发 trap,便于调试

;; 使用导入函数进行调试输出
(import "debug" "log_i32" (func $log (param i32)))

(func $debug_example (param $value i32)
  ;; 记录参数值
  (call $log (local.get $value))
  
  ;; 继续处理...)

A.15.2 代码组织建议

;; 使用有意义的函数和变量名
(func $calculate_fibonacci (param $n i32) (result i32)
  (local $prev i32)
  (local $curr i32)
  ;; 清晰的实现)

;; 添加注释说明复杂逻辑
;; 计算 x 的平方根(牛顿法)
(func $sqrt_newton (param $x f64) (result f64)
  ;; 实现...)

;; 将相关功能分组到同一模块
(module
  ;; 数学函数组
  (func $add ...)
  (func $multiply ...)
  (func $power ...)
  
  ;; 字符串处理组
  (func $strlen ...)
  (func $strcmp ...)
  (func $strcpy ...))

📖 参考说明

  • 所有指令都区分大小写
  • 标签名(如 $name)是可选的,也可以使用数字索引
  • 某些高级指令需要特定的 WebAssembly 提案支持
  • 性能特性可能因不同的 WebAssembly 运行时而异

🔗 相关章节