wasm指令集

参考:《WebAssembly原理与核心技术》

WebAssembly指令集

Wasm指令的操作码固定为一个字节,因此指令集最多只能包含256条指令.
Wasm规范一共定义了178条指令,可以分为5大类:

  1. 控制指令,共13条
  2. 参数指令,共2条
  3. 变量指令,共5条
  4. 内存指令,共25条
  5. 数值指令,共133条,又可进一步分为常量指令\测试指令\比较指令\算术运算指令\类型转换指令

立即数

Wasm指令包含两部分信息:操作码和操作数,操作数又分为静态操作数和动态操作数

静态操作数直接编码在指令里,又称为静态立即参数,简称立即数

动态操作数在运行时从操作数栈获取,如无特殊说明操作数就是指动态操作数

1
2
3
4
type Instruction struct {
Opcode byte
Args interface{} // 立即数
}

1.内存指令

内存加载/存储系列指令需要指定内存偏移量和对齐提示

1
2
3
4
type MemArg struct {
Align uint32
Offset uint32
}

2.block和loop指令

Wasm摒弃了GOTO和JUMP指令(ps:GOTO语句会导致代码无法阅读),使用block\loop\if这3种指令定义顺序\循环\分支结构的起点,以end指令为终点,形成内部是嵌套的指令序列.使用br系列指令跳出block和if块,或者重新开始loop块.这三种指令很像内联函数,可以带有参数值和结果值

block指令和loop指令在代码结构上完全一样

1
2
3
4
5
6
type BlockType = int32

type BlockArgs struct {
BT BlockType
Instrs []Instruction
}

3.if指令

if块稍微复杂一些,其内部的指令序列被else指令一分为二

1
2
3
4
5
type IfArgs struct {
BT BlockType
Instrs1 []Instruction
Instrs2 []Instruction
}

4.br_table指令

br系列指令包括4条:br\br_if\br_table和return,其中return指令没有立即数,br和br_if指令的立即数是索引类型,没有必要单独定义,只有br_table指令的立即数包含一个跳转表和默认跳转标签

1
2
3
4
type BrTableArgs struct {
Labels []LabelIdx
Default LabelIdx
}

操作数

Wasm规范实际上定义了一台概念上的栈式虚拟机.绝大多数Wasm指令都是基于一个虚拟栈工作:从栈顶弹出若干个数,进行计算,然后把结果压栈;如上文所说,我们把这些运行时位于栈顶并被指令操纵的数叫做指令的动态操作数,简称操作数,这个栈称为操作数栈.为了实现控制指令,Wasm还需要一个控制栈,为了不产生歧义,将操作数栈简称为栈

由于采用了栈式虚拟机,大部分Wasm指令都很短,这是因为操作数已经存储在栈上了.例如i32.add指令只有一个操作码0x6A,在执行时,这条指令从栈顶弹出两个i32类型的整数相加,然后把结果压栈.这一设计使得Wasm字节码非常紧凑

指令分析

(未完待续)