本文档描述了portableWebAssembly 模块的二进制编码。
二进制编码是模块信息的密集表示,支持小文件、快速解码和减少内存使用。有关详细信息,请参见理由文件。
[:独角兽:][未来通用]= 计划的 [未来][未来通用] 功能
编码分为三层:
- 第 0 层是字节码指令和相关数据结构的简单二进制编码。这种编码很密集,交互起来很简单,因此适用于 JIT、插装工具和调试等场景。
- 第一层:unicorn: 在第 0 层之上提供结构压缩,利用关于语法树及其节点的性质的特定知识。结构压缩引入了更有效的值编码,重新排列模块中的值,并修剪结构相同的树节点。
- 第二层:unicorn: 第 2 层应用通用压缩算法,如gzip和Brotli,这些算法已在浏览器和其他工具中可用。
最重要的是,分层方法允许以增量方式进行开发和标准化。例如,第 1 层和第 2 层编码技术可以通过应用程序级解压缩到下面的层来试验。随着压缩技术的稳定,它们可以被标准化并转移到本机实现中。
有关第 1 层结构压缩的建议,请参见 [建议的第 1 层压缩:unicorn:][未来压缩]。
位的_名词_无符号整数,按小端顺序以_名词_/8 字节表示。_名词_为 8、16 或 32。
LEB128可变长度整数,限于_名词_位(即,值 [0,2^n-1]),由_最多_可能包含填充 0x80
字节的 ceil(n/7)字节表示。
注意:目前,唯一使用的大小是 varuint1
、 varuint7
和 varuint32
,其中前两个用于与潜在的未来扩展兼容。
长度签名 LEB128可变的整数,限于_名词_位(即,值 [-2^(n-1),+2^(n-1)-1]),由_最多_可能包含填充 0x80
或 0xFF
字节的 ceil(n/7)字节表示。
注意:目前使用的尺寸只有 varint7
、 varint32
和 varint64
。
在 MVP 中,的操作码指示全部编码在单个字节中,因为操作码少于 256 个。未来的功能(如SIMD和atomics)将使总数超过 256,因此需要扩展方案,将一个或多个单字节值指定为多字节操作码的前缀。
所有类型都通过其编码的第一个字节(表示类型构造函数)的负值 varint7
来区分:
Opcode | 类型构造函数 |
---|---|
-0x01 (即字节 0x7f ) |
i32 |
-0x02 (即字节 0x7e ) |
i64 |
-0x03 (即字节 0x7d ) |
f32 |
-0x04 (即字节 0x7c ) |
f64 |
-0x10 (即字节 0x70 ) |
anyfunc |
-0x20 (即字节 0x60 ) |
func |
-0x40 (i.e., the byte 0x40 ) |
表示空 block_type 的伪类型 |
其中一些字段后面会有其他字段,请参阅下文。
注意:间隙是为 Future:unicorn: 扩展保留的。有符号方案的使用是为了使类型可以与类型部分中的(正)索引共存于单个空间中,这可能与类型系统的未来扩展有关。
A varint7
表示 Avalue type。其中之一:
I32
I64
F32
F64
如上面所编码的。
a varint7
表示区块签名。这些类型编码为:
- 指示具有单个结果的签名的 [
value_type
](# 值 _ 类型) - 或者
-0x40
(即,字节0x40
)指示具有 0 结果的签名。
A varint7
表示 Atable中元素的类型。在 MVP 中,只有一种类型可用:
- [
anyfunc
](semantics.MD# 表)
注意:在 Future:unicorn: 中,可能允许其他元素类型。
函数签名的描述。它的类型构造函数后面有一个附加说明:
Field | Type | 描述 |
---|---|---|
form | varint7 |
上面定义的 func 类型构造函数的值 |
param_count | varuint32 |
函数的参数数目 |
param_types | value_type* |
函数的参数类型 |
return_count | varuint1 |
函数的结果数 |
return_type | value_type? |
函数的结果类型(如果返回 _ 计数为 1) |
注意:在 Future:unicorn: 中, return_count
return_type
可以泛化为允许多个值。
全局变量的说明。
Field | Type | 描述 |
---|---|---|
content_type | value_type |
值的类型 |
mutability | varuint1 |
0 如果不可变, 1 如果可变 |
表的说明。
Field | Type | 描述 |
---|---|---|
element_type | elem_type |
元素的类型 |
limits | resizable_limits |
看到below |
对记忆的描述。
Field | Type | 描述 |
---|---|---|
limits | resizable_limits |
看到below |
指示要导入或定义的定义类型的单字节无符号整数:
0
表示Function
import“或”definition1
表示Table
import“或”definition2
表示Memory
import“或”definition3
表示Global
import“或”definition
Field | Type | 描述 |
---|---|---|
flags | varuint1 |
1 如果存在最大值字段, 0 则为 |
initial | varuint32 |
初始长度(以表元素或 WASM 页面为单位) |
maximum | varuint32 ? |
仅在指定 flags 时存在 |
注意:在 Future:unicorn: 中,“Flags”字段可以被改变为 varuint32
例如包括用于在线程之间共享的标志。
的初始化表达式编码是表达式的正常编码,后面是作为分隔符的 end
操作码。
请注意 get_global
,在初始值设定项中,表达式只能引用不可变的导入全局变量,并且的 init_expr
所有使用只能出现在导入部分之后。
以下文档记录了当前的原型格式。此格式基于并取代了 V8 原生原型格式,该格式最初位于公共设计文件。
该模块以两个字段的前导码开始:
Field | Type | 描述 |
---|---|---|
magic number | uint32 |
幻数 0x6d736100 (即“\0asm”) |
version | uint32 |
版本号 0x1 |
模块前导码之后是一系列部分。每个部分由一个 1 字节区段代码标识,该字节对已知部分或自定义部分进行编码。然后是部分长度和有效载荷数据。已知部分具有非零 ID,而自定义部分具有一个 0
ID,后跟一个标识字符串,作为有效负载的一部分。
Field | Type | 描述 |
---|---|---|
id | varuint7 |
区段代码 |
payload_len | varuint32 |
此部分的大小(以字节为单位) |
name_len | varuint32 ? |
长度( name 以字节为单位),如果 id == 0 |
name | bytes ? |
节名:有效的 UTF-8 字节序列,如果 id == 0 |
payload_data | bytes |
本节内容,长度 payload_len - sizeof(name) - sizeof(name_len) |
每个已知部分都是可选的,最多只能出现一次。自定义部分都具有相同 id
的(0),并且可以不唯一地命名(组成其名称的所有字节可以相同)。
自定义部分旨在用于调试信息、未来发展或第三方扩展。对于 MVP,我们使用特定的自定义部分(名称节)来显示调试信息。
如果 WebAssembly 实现在模块验证或编译期间解释任何自定义节的有效负载,则该有效负载中的错误不得使模块无效。
下面列表中的已知部分不能无序显示,而自定义部分可以以任何顺序散布在列表的任何元素之前、之间以及之后。某些自定义节可能有自己的排序和基数要求。例如,名称节最多出现一次,紧跟在数据节之后。违反此类要求最多可能导致实现忽略该部分,而不会使模块无效。
每个部分的内容都在其 payload_data
中编码。
节名称 | Code | Description |
---|---|---|
Type | 1 |
函数签名声明 |
Import | 2 |
Import declarations |
Function | 3 |
Function declarations |
Table | 4 |
间接函数表和其他表 |
Memory | 5 |
Memory attributes |
Global | 6 |
Global declarations |
Export | 7 |
Exports |
Start | 8 |
开始函数声明 |
Element | 9 |
Elements section |
Code | 10 |
函数主体(代码) |
Data | 11 |
Data segments |
最后一个当前部分的结尾必须与模块的最后一个字节一致。最短的有效模块是 8 个字节( magic number
, version
,后面是零节)。
type 部分声明将在模块中使用的所有函数签名。
Field | Type | 描述 |
---|---|---|
count | varuint32 |
要跟随的类型条目的计数 |
entries | func_type* |
重复的类型项,如所述above |
注意:在 Future:unicorn: 中,此部分也可能包含其他形式的类型条目,可以通过 form
类型编码的字段进行区分。
import 部分声明将在模块中使用的所有导入。
Field | Type | 描述 |
---|---|---|
count | varuint32 |
要跟随的导入条目的计数 |
entries | import_entry* |
如下所述的重复导入条目 |
Field | Type | 描述 |
---|---|---|
module_len | varuint32 |
长度( module_str 单位:字节) |
module_str | bytes |
模块名称:有效的 UTF-8 字节序列 |
field_len | varuint32 |
长度( field_str 单位:字节) |
field_str | bytes |
字段名:有效的 UTF-8 字节序列 |
kind | external_kind |
要导入的定义的种类 |
后跟,如果 kind
是 Function
:
Field | Type | 描述 |
---|---|---|
type | varuint32 |
函数签名的类型索引 |
或者,如果 kind
是 Table
:
Field | Type | 描述 |
---|---|---|
type | table_type |
导入表的类型 |
或者,如果 kind
是 Memory
:
Field | Type | 描述 |
---|---|---|
type | memory_type |
导入内存的类型 |
或者,如果 kind
是 Global
:
Field | Type | 描述 |
---|---|---|
type | global_type |
导入的全局变量的类型 |
请注意,在 MVP 中,只能导入不可变全局变量。
函数部分_声明_是模块中所有函数的签名(它们的定义显示在中代码部分)。
Field | Type | 描述 |
---|---|---|
count | varuint32 |
要跟随的签名索引的计数 |
types | varuint32* |
类型部分中的索引序列 |
A表节的编码:
Field | Type | 描述 |
---|---|---|
count | varuint32 |
指示模块定义的表数 |
entries | table_type* |
所述above的重复 table_type 条目 |
在 MVP 中,表的数量必须不超过 1。
身份证: memory
A存储器部分的编码:
Field | Type | 描述 |
---|---|---|
count | varuint32 |
表示模块定义的存储器数量 |
entries | memory_type* |
所述above的重复 memory_type 条目 |
请注意,初始/最大值字段以单位WebAssembly 页面指定。
在 MVP 中,记忆数量必须不超过 1。
的编码全球部分:
Field | Type | 描述 |
---|---|---|
count | varuint32 |
全局变量条目计数 |
globals | global_variable* |
全局变量,如下所述 |
每个 global_variable
声明一个给定类型、可变性和给定初始值设定项的单个全局变量。
Field | Type | 描述 |
---|---|---|
type | global_type |
变量的类型 |
init | init_expr |
全局的初始值 |
请注意,在 MVP 中,只能导出不可变的全局变量。
的编码导出部分:
Field | Type | 描述 |
---|---|---|
count | varuint32 |
要跟随的导出条目的计数 |
entries | export_entry* |
如下所述的重复导出条目 |
Field | Type | 描述 |
---|---|---|
field_len | varuint32 |
长度( field_str 单位:字节) |
field_str | bytes |
字段名:有效的 UTF-8 字节序列 |
kind | external_kind |
要导出的定义的种类 |
index | varuint32 |
索引到相应索引空间的 |
例如,如果“种类”是 Function
,则“索引”是功能索引。请注意,在 MVP 中,内存或表导出的唯一有效索引值是 0。
开始部分声明启动功能。
Field | Type | 描述 |
---|---|---|
index | varuint32 |
开始功能索引 |
的编码元素部分:
Field | Type | 描述 |
---|---|---|
count | varuint32 |
要跟随的元素段数 |
entries | elem_segment* |
重复的元素片段如下所述 |
A elem_segment
为:
Field | Type | 描述 |
---|---|---|
index | varuint32 |
表索引(MVP 中的 0) |
offset | init_expr |
i32 初始化器表达式,用于计算放置元素的偏移量 |
num_elem | varuint32 |
要遵循的元素数量 |
elems | varuint32* |
的功能指标顺序 |
身份证: code
代码部分包含模块中每个函数的主体。本节中定义的功能部分和函数体中声明的函数计数必须相同,并且 i
第个声明与 i
第个函数体相对应。
Field | Type | 描述 |
---|---|---|
count | varuint32 |
要跟随的函数体的计数 |
bodies | function_body* |
的函数体顺序 |
数据段声明加载到线性内存中的初始化数据。
Field | Type | 描述 |
---|---|---|
count | varuint32 |
要跟随的数据段的计数 |
entries | data_segment* |
重复的数据段如下所述 |
A data_segment
为:
Field | Type | 描述 |
---|---|---|
index | varuint32 |
线性记忆指数(MVP 中的 0) |
offset | init_expr |
i32 初始化器表达式,用于计算放置数据的偏移量 |
size | varuint32 |
大小 data (以字节为单位) |
data | bytes |
字节序列 size |
自定义部分 name
字段: "name"
名称部分是一个自定义部分。因此,它使用 ID 0
后跟名称字符串 "name"
进行编码。与所有自定义节一样,此节格式错误不会导致模块验证失败。这取决于实现如何处理格式错误或部分格式错误的名称节。在模块实例化之后,如果需要调试,WebAssembly 实现也可以自由选择延迟读取和处理此部分。
名称部分可能只出现一次,并且只出现在数据节。期望在浏览器或其他开发环境中查看二进制 WebAssembly 模块时,此部分中的数据将用作中文本格式的函数和局部变量的名称。
“名称”部分包含一系列名称子部分:
Field | Type | 描述 |
---|---|---|
name_type | varuint7 |
识别本小节中包含的名称类型的代码 |
name_payload_len | varuint32 |
此子部分的大小(字节) |
name_payload_data | bytes |
本节内容,长度 name_payload_len |
由于名称子部分具有给定的长度,因此引擎可以跳过未知或不需要的子部分。当前有效 name_type
代码列表为:
Name Type | Code | 描述 |
---|---|---|
Module | 0 |
为模块指定名称 |
Function | 1 |
为函数指定名称 |
Local | 2 |
为函数中的局部变量指定名称 |
出现时,子节必须按此顺序出现,且最多出现一次。最后一个子段的结尾必须与名称段的最后一个字节一致,才能成为格式良好的名称段。
模块名称子部分为模块本身指定一个名称。它只包含一个字符串:
Field | Type | 描述 |
---|---|---|
name_len | varuint32 |
长度( name_str 单位:字节) |
name_str | bytes |
名称的 UTF-8 编码 |
在以下小节中,A name_map
编码为:
Field | Type | 描述 |
---|---|---|
count | varuint32 |
IN 名称的 naming 数量 |
names | naming* |
按索引排序的 naming 序列 |
其中 A naming
编码为:
Field | Type | 描述 |
---|---|---|
index | varuint32 |
正在命名的索引 |
name_len | varuint32 |
长度( name_str 单位:字节) |
name_str | bytes |
名称的 UTF-8 编码 |
函数名称子部分是 name_map
将名称分配给的函数索引空间子集(导入和模块定义)。
每个函数最多只能命名一次。多次命名函数会导致节的格式不正确。
但是,名称不必是唯一的。可以为多个函数指定相同的名称。这在 C++ 程序中很常见,其中组成二进制文件的多个编译单元可以包含具有相同名称的本地函数。
局部名称子部分 name_map
将 s 分配给中函数索引空间的函数子集(导入和模块定义)。 name_map
对于给定的函数,将名称分配给局部变量索引的子集。
Field | Type | 描述 |
---|---|---|
count | varuint32 |
函数中的 local_names 计数 |
funcs | local_names* |
按索引排序的 local_names 序列 |
其中 A local_name
编码为:
Field | Type | 描述 |
---|---|---|
index | varuint32 |
正在命名其局部变量的函数的索引 |
local_map | name_map |
将名称分配给本地索引 |
函数体由一系列局部变量声明组成,后面跟有字节码指令。根据下表的定义,指令编码为opcode后跟零或更多立即。每个函数体必须以 end
操作码结束。
Field | Type | 描述 |
---|---|---|
body_size | varuint32 |
要跟随的函数体的大小(以字节为单位) |
local_count | varuint32 |
本地条目数 |
locals | local_entry* |
局部变量 |
code | byte* |
函数的字节码 |
end | byte |
0x0b ,表示主体的末端 |
每个局部条目声明给定类型的多个局部变量。拥有多个相同类型的条目是合法的。
Field | Type | 描述 |
---|---|---|
count | varuint32 |
以下类型的局部变量的数目 |
type | value_type |
变量的类型 |
控制流操作符(在这里描述)
Name | Opcode | Immediates | 描述 |
---|---|---|---|
unreachable |
0x00 |
立即诱捕 | |
nop |
0x01 |
无操作 | |
block |
0x02 |
sig : block_type |
开始一个表达式序列,产生 0 或 1 值 |
loop |
0x03 |
sig : block_type |
开始也可以形成控制流循环的块 |
if |
0x04 |
sig : block_type |
开始 If 表达式 |
else |
0x05 |
开始 If 的 Else 表达式 | |
end |
0x0b |
结束块、循环或 if | |
br |
0x0c |
relative_depth : varuint32 |
以外部嵌套块为目标的打断 |
br_if |
0x0d |
relative_depth : varuint32 |
以外部嵌套块为目标的条件中断 |
br_table |
0x0e |
see below | 分支表控制流构造 |
return |
0x0f |
从该函数返回零或一个值 |
AND if
运算符的 block
_西格_字段指定函数签名,这些签名描述它们对操作数堆栈的使用。
br_table
运算符有一个立即数操作数,其编码如下:
Field | Type | 描述 |
---|---|---|
target_count | varuint32 |
目标 _ 表中的条目数 |
target_table | varuint32* |
指示要中断到的外部块或循环的目标条目 |
default_target | varuint32 |
在默认情况下要中断到的外部块或循环 |
br_table
操作符实现了一个间接分支。它接受一个可选的值参数(像其他分支一样)和一个附加 i32
的表达式作为输入,并在给定的偏移量处分支到块或循环 target_table
。如果输入值超出范围,则 br_table
分支到默认目标。
注意:这里和其他地方的操作码空间中的间隙是为 Future:unicorn: 扩展保留的。
调用操作员(在这里描述)
Name | Opcode | Immediates | 描述 |
---|---|---|---|
call |
0x10 |
function_index : varuint32 |
通过其index调用函数 |
call_indirect |
0x11 |
type_index : varuint32 , reserved : varuint1 |
使用预期的签名间接调用函数 |
该 call_indirect
运算符接受一系列函数参数,并将表中的索引作为最后一个操作数。其 reserved
立即值供 Future:unicorn: 使用,并且必须 0
在 MVP 中。
参数运算符(在这里描述)
Name | Opcode | Immediates | 描述 |
---|---|---|---|
drop |
0x1a |
忽略值 | |
select |
0x1b |
根据条件选择两个值之一 |
变量访问(在这里描述)
Name | Opcode | Immediates | 描述 |
---|---|---|---|
get_local |
0x20 |
local_index : varuint32 |
读取局部变量或参数 |
set_local |
0x21 |
local_index : varuint32 |
编写局部变量或参数 |
tee_local |
0x22 |
local_index : varuint32 |
编写局部变量或参数并返回相同的值 |
get_global |
0x23 |
全球 _ 指数: varuint32 |
read a global variable |
set_global |
0x24 |
全球 _ 指数: varuint32 |
write a global variable |
与内存相关的运算符(在这里描述)
Name | Opcode | Immediate | 描述 |
---|---|---|---|
i32.load |
0x28 |
memory_immediate |
load from memory |
i64.load |
0x29 |
memory_immediate |
load from memory |
f32.load |
0x2a |
memory_immediate |
load from memory |
f64.load |
0x2b |
memory_immediate |
load from memory |
i32.load8_s |
0x2c |
memory_immediate |
load from memory |
i32.load8_u |
0x2d |
memory_immediate |
load from memory |
i32.load16_s |
0x2e |
memory_immediate |
load from memory |
i32.load16_u |
0x2f |
memory_immediate |
load from memory |
i64.load8_s |
0x30 |
memory_immediate |
load from memory |
i64.load8_u |
0x31 |
memory_immediate |
load from memory |
i64.load16_s |
0x32 |
memory_immediate |
load from memory |
i64.load16_u |
0x33 |
memory_immediate |
load from memory |
i64.load32_s |
0x34 |
memory_immediate |
load from memory |
i64.load32_u |
0x35 |
memory_immediate |
load from memory |
i32.store |
0x36 |
memory_immediate |
store to memory |
i64.store |
0x37 |
memory_immediate |
store to memory |
f32.store |
0x38 |
memory_immediate |
store to memory |
f64.store |
0x39 |
memory_immediate |
store to memory |
i32.store8 |
0x3a |
memory_immediate |
store to memory |
i32.store16 |
0x3b |
memory_immediate |
store to memory |
i64.store8 |
0x3c |
memory_immediate |
store to memory |
i64.store16 |
0x3d |
memory_immediate |
store to memory |
i64.store32 |
0x3e |
memory_immediate |
store to memory |
current_memory |
0x3f |
reserved : varuint1 |
查询内存大小 |
grow_memory |
0x40 |
reserved : varuint1 |
增加内存大小 |
memory_immediate
类型编码如下:
Name | Type | 描述 |
---|---|---|
flags | varuint32 |
当前包含最低有效位对齐的位域,编码为 log2(alignment) |
offset | varuint32 |
偏移的值 |
正如编码所暗示的 log2(alignment)
,比对必须是 2 的幂。作为额外的验证标准,比对必须小于或等于自然比对。最低有效位之后 log(memory-access-size)
的位必须设置为 0. 这些位保留给 [未来:unicorn:][未来线程] 使用(例如,用于共享内存排序要求)。
current_memory
AND grow_memory
运算符的 reserved
立即值供 Future:unicorn: 使用,并且在 MVP 中必须为 0。
常量(在这里描述)
Name | Opcode | Immediates | 描述 |
---|---|---|---|
i32.const |
0x41 |
value : varint32 |
常数值解释为 i32 |
i64.const |
0x42 |
value : varint64 |
常数值解释为 i64 |
f32.const |
0x43 |
value : uint32 |
常数值解释为 f32 |
f64.const |
0x44 |
value : uint64 |
常数值解释为 f64 |
比较运算符(在这里描述)
Name | Opcode | Immediate | 描述 |
---|---|---|---|
i32.eqz |
0x45 |
||
i32.eq |
0x46 |
||
i32.ne |
0x47 |
||
i32.lt_s |
0x48 |
||
i32.lt_u |
0x49 |
||
i32.gt_s |
0x4a |
||
i32.gt_u |
0x4b |
||
i32.le_s |
0x4c |
||
i32.le_u |
0x4d |
||
i32.ge_s |
0x4e |
||
i32.ge_u |
0x4f |
||
i64.eqz |
0x50 |
||
i64.eq |
0x51 |
||
i64.ne |
0x52 |
||
i64.lt_s |
0x53 |
||
i64.lt_u |
0x54 |
||
i64.gt_s |
0x55 |
||
i64.gt_u |
0x56 |
||
i64.le_s |
0x57 |
||
i64.le_u |
0x58 |
||
i64.ge_s |
0x59 |
||
i64.ge_u |
0x5a |
||
f32.eq |
0x5b |
||
f32.ne |
0x5c |
||
f32.lt |
0x5d |
||
f32.gt |
0x5e |
||
f32.le |
0x5f |
||
f32.ge |
0x60 |
||
f64.eq |
0x61 |
||
f64.ne |
0x62 |
||
f64.lt |
0x63 |
||
f64.gt |
0x64 |
||
f64.le |
0x65 |
||
f64.ge |
0x66 |
数值运算符(在这里描述)
Name | Opcode | Immediate | 描述 |
---|---|---|---|
i32.clz |
0x67 |
||
i32.ctz |
0x68 |
||
i32.popcnt |
0x69 |
||
i32.add |
0x6a |
||
i32.sub |
0x6b |
||
i32.mul |
0x6c |
||
i32.div_s |
0x6d |
||
i32.div_u |
0x6e |
||
i32.rem_s |
0x6f |
||
i32.rem_u |
0x70 |
||
i32.and |
0x71 |
||
i32.or |
0x72 |
||
i32.xor |
0x73 |
||
i32.shl |
0x74 |
||
i32.shr_s |
0x75 |
||
i32.shr_u |
0x76 |
||
i32.rotl |
0x77 |
||
i32.rotr |
0x78 |
||
i64.clz |
0x79 |
||
i64.ctz |
0x7a |
||
i64.popcnt |
0x7b |
||
i64.add |
0x7c |
||
i64.sub |
0x7d |
||
i64.mul |
0x7e |
||
i64.div_s |
0x7f |
||
i64.div_u |
0x80 |
||
i64.rem_s |
0x81 |
||
i64.rem_u |
0x82 |
||
i64.and |
0x83 |
||
i64.or |
0x84 |
||
i64.xor |
0x85 |
||
i64.shl |
0x86 |
||
i64.shr_s |
0x87 |
||
i64.shr_u |
0x88 |
||
i64.rotl |
0x89 |
||
i64.rotr |
0x8a |
||
f32.abs |
0x8b |
||
f32.neg |
0x8c |
||
f32.ceil |
0x8d |
||
f32.floor |
0x8e |
||
f32.trunc |
0x8f |
||
f32.nearest |
0x90 |
||
f32.sqrt |
0x91 |
||
f32.add |
0x92 |
||
f32.sub |
0x93 |
||
f32.mul |
0x94 |
||
f32.div |
0x95 |
||
f32.min |
0x96 |
||
f32.max |
0x97 |
||
f32.copysign |
0x98 |
||
f64.abs |
0x99 |
||
f64.neg |
0x9a |
||
f64.ceil |
0x9b |
||
f64.floor |
0x9c |
||
f64.trunc |
0x9d |
||
f64.nearest |
0x9e |
||
f64.sqrt |
0x9f |
||
f64.add |
0xa0 |
||
f64.sub |
0xa1 |
||
f64.mul |
0xa2 |
||
f64.div |
0xa3 |
||
f64.min |
0xa4 |
||
f64.max |
0xa5 |
||
f64.copysign |
0xa6 |
转换(在这里描述)
Name | Opcode | Immediate | 描述 |
---|---|---|---|
i32.wrap/i64 |
0xa7 |
||
i32.trunc_s/f32 |
0xa8 |
||
i32.trunc_u/f32 |
0xa9 |
||
i32.trunc_s/f64 |
0xaa |
||
i32.trunc_u/f64 |
0xab |
||
i64.extend_s/i32 |
0xac |
||
i64.extend_u/i32 |
0xad |
||
i64.trunc_s/f32 |
0xae |
||
i64.trunc_u/f32 |
0xaf |
||
i64.trunc_s/f64 |
0xb0 |
||
i64.trunc_u/f64 |
0xb1 |
||
f32.convert_s/i32 |
0xb2 |
||
f32.convert_u/i32 |
0xb3 |
||
f32.convert_s/i64 |
0xb4 |
||
f32.convert_u/i64 |
0xb5 |
||
f32.demote/f64 |
0xb6 |
||
f64.convert_s/i32 |
0xb7 |
||
f64.convert_u/i32 |
0xb8 |
||
f64.convert_s/i64 |
0xb9 |
||
f64.convert_u/i64 |
0xba |
||
f64.promote/f32 |
0xbb |
重新解释(在这里描述)
Name | Opcode | Immediate | 描述 |
---|---|---|---|
i32.reinterpret/f32 |
0xbc |
||
i64.reinterpret/f64 |
0xbd |
||
f32.reinterpret/i32 |
0xbe |
||
f64.reinterpret/i64 |
0xbf |