WebAssembly - WASM



WebAssembly 也称为 wasm,是对 Javascript 的改进。它被设计为像 javascript 一样在浏览器中运行,也可以与 nodejs 一起运行。当任何高级语言(如 C、C++、Rust)被编译时,您会得到 wasm 输出。

考虑以下 C 程序:

int factorial(int n) {
   if (n == 0) 
      return 1; 
   else 
      return n * factorial(n-1); 
}

使用 WasmExplorer(可在 https://mbebenita.github.io/WasmExplorer/ 获取)获取如下所示的编译代码:

Wasm Explorer

阶乘程序的 WebAssembly 文本格式如下所示:

(module 
   (table 0 anyfunc) 
   (memory $0 1) 
   (export "memory" (memory $0)) (export "factorial" (func $factorial)) 
   (func $factorial (; 0 ;) (param $0 i32) (result i32)
      (local $1 i32) 
      (local $2 i32) 
      (block $label$0 
         (br_if $label$0 
            (i32.eqz 
               (get_local $0) 
            )
         )
         (set_local $2 
            (i32.const 1) 
         ) 
         (loop $label$1 
            (set_local $2 
               (i32.mul 
                  (get_local $0) (get_local $2) 
               ) 
            ) 
            (set_local $0 
               (tee_local $1        (i32.add 
                  (get_local $0) (i32.const -1) 
               ) 
               ) 
            ) 
            (br_if $label$1      (get_local $1) 
            ) 
         ) 
         (return 
            (get_local $2)
         ) 
      ) 
      (i32.const 1) 
   )
)

使用 Wat2Wasm 工具,您可以查看 WASM 代码,就像下面提到的那样:

Wat2Wasm Tool

开发人员不应该用 wasm 编写代码或学习用它编写代码,因为它主要是在编译高级语言时生成的。

栈式机器模型

在 WASM 中,所有指令都压入栈中。参数被弹出,结果被压回栈中。

考虑以下 WebAssembly 文本格式,它添加了 2 个数字:

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

函数的名称为 $add,它接收 2 个参数 $a 和 $b。结果为 32 位整数类型。局部变量使用 get_local 访问,加法运算使用 i32.add 执行。

执行期间添加 2 个数字的栈表示如下:

Stack

步骤 1 中 - 执行 get_local $a 指令,第一个参数即 $a 被压入栈中。

步骤 2 中 - 在执行 get_local $b 指令期间,第二个参数即 $b 被压入栈中。

步骤 3 中 - i32.add 的执行将从栈中弹出元素,并将结果压回栈中。最终留在栈中的值是函数 $add 的结果。

广告