前言

WebAssembly 也称为 wasm,它是对 Javascript 的改进。

它旨在像 javascript 一样在浏览器中运行,也可以 在nodejs环境中运行。

当任何高级语言如 CC++Rust 被编译时,你可以得到 wasm 输出。

工具

示例

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

将上述代码放入左侧源码输入框然后编译,效果如下所示:

输入与编译

wat 文本内容 转为 wasm 的方式,将文本格式内容贴到输入框内,立即可以看到 wasm 汇编代码

wat2wasm-示例

栈模型机

WASM 中,所有指令都被推入堆栈。参数被弹出,结果被推回堆栈。 查看关于两个数的加法 WebAssembly 程序−

(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 个数字的堆栈表示将如下−

栈模型机内存.png

  • 步骤:
步骤描述
1执行 get_local $a指令,即第一个参数,即 $a 入栈。
2在执行 get_local $b指令时,第二个参数(即$b入栈 入栈)。
3i32.add 的执行将弹出堆栈中的元素,并将结果推回堆栈。堆栈内最终保留的值是函数$add的结果。

安装依赖

在这一章中,将学习如何安装 Emscripten SDK来编译C/C++Emscripten 是一款低级别虚拟机器 (LLVM),它采用 C/C++ 生成的字节代码,并将其编译到 JavaScript 中,以便于在浏览器内执行。

  • 安装 sdk

克隆项目源码:

git clone https://github.com/emscripten-core/emsdk.git

下一步 进入emsdk 目录并获取最新代码并安装最新版本的 sdk

cd emsdk
## windows
emsdk install latest
## linux 这个命令将需要一些时间来安装必要的工具,如Java,Python等。请按照以下代码−
./emsdk install latest
  • 激活环境
## windows
emsdk_env.bat
## linux
source ./emsdk_env.sh

编译

我们已经完成了安装 emsdk,现在可以编译 CC++ 代码

emcc source.c or source.cpp -s WASM=1 -o source.html

输出将为您提供一个source.html文件、source.jssource.wasm 文件。js api,将获source.wasm ,当你点击source.html在浏览器中。你可以看到输出

仅获取 wasm 文件。此命令将只为您提供source.wasm

emcc source.c or source.cpp -s STANDALONE_WASM

在线编译工具

WebAssembly Studio

webassembly在线编译工具

首先,您可以单击 Empty C Project, Empty Rust Project, Empty Wat Project 将他们编译为 wasm

它有生成,运行来构建代码并检查输出。下载按钮允许您下载。wasm 文件,可用于在浏览器内测试。此工具非常有助于编译 CRust 代码并检查输出

在线编辑代码并可以在线编译和运行

WASM 程序结构

  • 示例代码
(module
  (type $t0 (func))
  (type $t1 (func (result i32)))
  (func $__wasm_call_ctors (type $t0))
  (func $main (export "main") (type $t1) (result i32)
    i32.const 42)
  (table $T0 1 1 anyfunc)
  (memory $memory (export "memory") 2)
  (global $g0 (mut i32) (i32.const 66560))
  (global $__heap_base (export "__heap_base") i32 (i32.const 66560))
  (global $__data_end (export "__data_end") i32 (i32.const 1024)))

WebAssembly,也称为 WASM,是开发的二进制格式低级别代码,以最有效的方式在浏览器内执行

概念

  • 类型
  • 指令

WebAssembly 中的值用于存储复杂数据,例如文本、字符串和向量。

WebAssembly 支持以下内容 -

  • Bytes 字节
  • Integers 整型
  • Floating point 浮点型
  • Names 名称
Bytes

字节是 WebAssemblyC 支持的最简单的值形式。其价值是16进制格式。 例如,以b为代表的字节也可以取自然数字n,其中n<256

整数

WebAssembly 中,支持整数如下

  • i32:32 位整数
  • i64: 64 位整数
浮点

WebAssembly 中支持的浮点数字如下

  • f32: 32 位浮点数
  • f64: 64 位浮点数
名称

名称是字符序列,由 Unicode 定义的标量值,可在此处给出的链接 unicode提供。

Types

WebAssembly 中的实体被归类为类型。所支持的类型如下所述−

  • Value Types
  • Result Types
  • Function Types
  • Limits
  • Memory Types
  • Table Types
  • Global Types
  • External Types
值类型

支持的值类型如下所述

  • i32:32 位整数
  • i64: 64 位整数
  • f32: 32 位浮点型
  • f64: 64 位浮点型
结果类型

括号内的值执行并存储在结果类型中。结果类型是由值组成的代码块执行的输出。

函数类型

函数类型将接收参数的向量,返回向量的结果。

functype::=[vec(valtype)]--> [vec(valtype)]
限制类型

限制是与内存和表类型相关的存储范围。

limits ::= {min u32, max u32}
内存类型

内存类型处理线性内存大小范围。

memtype ::= limits
表类型

表类型按分配给它的元素类型进行分类。

tabletype ::= limits elemtype
elemtype ::= funcref

表类型取决于分配给它的最小和最大尺寸的限制。

全局类型

全局类型 持有具体值、可以更改或保持不变的全局变量。、

globaltype ::= mut valtype
mut ::= const|var
外部类型

外部类型涉及导入和外部值。

externtype ::= func functype | table tabletype | mem memtype | global globaltype

指令

WebAssembly 遵循堆栈机模型的一系列指令。当 遵循时,指令入堆栈。 例如,函数的参数值从堆栈中弹出,结果入堆栈上。最终,堆栈中只有一个值,这就是结果。

一些常用的指令如下−

  • 数字指令
  • 变量指令
数字指令

数字指令是按数字值执行的操作。

eg:

nn, mm ::= 32|64
ibinop ::= add|sub|mul|div_sx|rem_sx|and|or|xor
irelop ::= eq | ne | lt_sx | gt_sx | le_sx | ge_sx
frelop ::= eq | ne | lt | gt | le | ge
变量指令

变量指令是关于获取本地和全局变量。

eg:

  • 访问本地变量
get_local $a
get_local $b
  • 设置本地变量
set_local $a
set_local $b
  • 获取全局变量
get_global $a
get_global $b
  • 设置全局变量
set_global $a
set_global $b

JS

WASM 之所以出现,并不是要取代 javascript,而是要处理某些难以用 javascript 处理的事情。

eg:

图像识别、CAD 应用程序、实时视频增强、VR 和增强现实、音乐应用程序、科学可视化和模拟、游戏、图像/视频编辑等任务很难用 javascript 来完成。

使用现在可以编译为 WebAssembly C/C++Rust 等高级语言,很容易完成上述任务。

WebAssembly 生成易于在浏览器中执行的二进制代码。

所以这里是 JavascriptWebAssembly 之间的比较列表。

参数JavascriptWebAssembly
代码您可以轻松地在 Javascript 本中编写代码。编写的代码是可读的,并保存为 .js。在浏览器中使用时,您需要使用<script>标。该代码可以以 WebAssembly形式以文本格式编写,并保存为.wat。很难以.wat格式编写代码。最好从其他高级语言中编译代码,而不是从.wat开始编写。 您无法在浏览器内执行.wat文件,并且必须使用可用的编译器或在线工具转换为.wasm
执行在浏览器中使用时,必须下载、解析、编译和优化用 javascript 编写的代码。已经编译成二进制格式
内存管理Javascript 在创建变量时分配内存,在未使用时释放内存并添加到垃圾收集中。WebAssembly 的内存是一个存储数据的阵列。您可以使用 Javascript API WebAssembly.memory().来分配内存。WebAssembly 以阵列格式存储,即易于理解和执行执行的平面内存模型。 WebAssembly 中内存模型的缺点是 <table><tr> <th>缺点</th></tr><tbody><tr><td>耗时复杂计算</td></tr><tr><td>不支持垃圾回收,不允许重复使用内存,造成内存浪费</td></tr></tbody></table>
加载事件、性能javascript 的情况下,当在浏览器内调用时,必须下载并解析 javascript 文件。稍后,解析器将源代码转换为字节代码,即 javascript 引擎在浏览器中执行代码。 Javascript 引擎非常强大,因此,与 WebAssembly 相比,javascript 的加载时间和性能非常快。最重要的目标是比 JavaScript 更快。 高级语言生成的 Wasm 代码尺寸较小,因此加载时间更快。 但是,像 GO 这样的语言,当编译到 wasm 时,会为一小块代码生成一个大文件大小。 WebAssembly 设计速度更快,可跨所有主要浏览器运行。与 javascript 相比,WebAssembly仍需要在性能方面增加许多改进。
调试Javascript 是可读的,易于调试。在浏览器中添加 javascript 代码的断点可轻松调试代码。WebAssembly 以文本格式提供代码,这是可读的,但是,仍然很难调试。Firefox 允许您在浏览器内以.wat 格式查看大体代码。 您无法在.wat中添加断点,这或许在将来可用的
浏览器支持Javascript 在所有浏览器中都工作得很好所有主要的 Web 浏览器都支持 。

发送一条友善的评论