WebAssembly - 文本格式化

  • 简述

    WebAssembly 具有称为 WASM 的二进制格式的代码。您还可以在 WebAssembly 中获取文本格式,它称为 WAT(WebAssembly 文本格式)。作为开发人员,您不应该在 WebAssembly 中编写代码,相反,您必须将 C、C++ 和 Rust 等高级语言编译为 WebAssembly。
  • 什么代码

    让我们逐步编写 WAT 代码。
    第 1 步- WAT 的起点是声明模块。
    
    (module)
    
    第 2 步 - 现在让我们以函数的形式添加一些功能。
    该函数声明如下 -
    
    (func <parameters/result> <local variables> <function body>)
    
    该函数以 func 关键字开头,后跟参数或结果。

    参数/结果

    参数和返回值作为结果。
    参数可以具有 wasm 支持的以下类型 -
    • i32: 32-bit integer
    • i64: 64-bit integer
    • f32: 32-bit float
    • f64: 64-bit float
    函数的参数如下所示 -
    • (param i32)
    • (param i64)
    • (param f32)
    • (param f64)
    结果将写如下 -
    • (result i32)
    • (result i64)
    • (result f32)
    • (result f64)
    具有参数和返回值的函数将定义如下 -
    
    (func (param i32) (param i32) (result i64) <function body>)
    

    局部变量

    局部变量是您在函数中需要的变量。函数的局部值将定义如下 -
    
    (func (param i32) (param i32) (local i32) (result i64) <function body>)
    

    函数体

    函数体是要执行的逻辑。最终程序将如下所示 -
    
    (module (func (param i32) (param i32) (local i32) (result i64) <function body>) )
    
    第 3 步 - 读取和设置参数和局部变量。
    要读取参数和局部变量,请使用get_localset_local命令。
    例子
    
    (module 
       (func (param i32) (param i32) (local i32) (result i64) get_local 0 
          get_local 1 
          get_local 2 
       ) 
    )
    
    根据函数签名,
    • get_local 0将给出参数 i32
    • get_local 1将给出下一个参数param i32
    • get_local 2将给出本地值 i32
    除了使用 0、1、2 之类的数值来引用参数和局部变量,您还可以在参数之前使用名称,在名称前加上美元符号。
    以下示例显示了如何将名称与参数和局部变量一起使用。
    例子
    
    (module 
       (func 
          (param $a i32) 
          (param $b i32) 
          (local $c i32) 
          (result i64) get_local $a get_local $b get_local $c 
       ) 
    )
    
    第 4 步- 函数体中的指令和执行。
    wasm 中的执行遵循堆栈策略。执行的指令在堆栈上一一发送。例如,指令 get_local $a 将压入值,它在堆栈上读取。
    i32.add这样将添加的指令将从堆栈中弹出元素。
    
    (func (param $a i32) (param $b i32) 
       get_local $a 
       get_local $b 
       i32.add
    )
    
    i32.add的指令是($a+$b)。i32.add 的最终值将被压入堆栈并分配给结果。
    如果函数签名声明了结果,则在执行结束时堆栈中应该有一个值。如果没有结果参数,则堆栈最后必须为空。
    因此,最终代码和函数体将如下所示 -
    
    (module 
       (func (param $a i32) (param $b i32) (result i32) 
          get_local $a
          get_local $b 
          i32.add
       )
    )
    
    第 5 步 - 调用函数。
    带有函数体的最终代码如步骤 4 所示。现在,要调用该函数,我们需要将其导出。
    要导出函数,可以使用 0,1 之类的索引值来完成,但是,我们也可以给出名称。该名称将以 $ 为前缀,并将添加在 func 关键字之后。
    例子
    
    (module 
       (func $add (param $a i32) (param $b i32) (result i32) 
          get_local $a 
          get_local $b i32.add
       ) 
    )
    
    必须使用 export 关键字导出函数 $add,如下所示 -
    
    (module 
       (func $add 
          (param $a i32) 
          (param $b i32) 
          (result i32) 
          get_local $a get_local $b i32.add
       ) 
       (export "add" (func $add))
    )
    
    要在浏览器中测试上述代码,您必须将其转换为二进制形式 (.wasm)。请参阅下一章,了解如何将.WAT 转换为 .WASM。