- WebAssembly 教程
- WebAssembly - 首页
- WebAssembly - 概述
- WebAssembly - 简介
- WebAssembly - WASM
- WebAssembly - 安装
- WebAssembly - 编译为 WASM 的工具
- WebAssembly - 程序结构
- WebAssembly - Javascript
- WebAssembly - Javascript API
- WebAssembly - 在 Firefox 中调试 WASM
- WebAssembly - “Hello World”
- WebAssembly - 模块
- WebAssembly - 验证
- WebAssembly - 文本格式
- WebAssembly - 将 WAT 转换为 WASM
- WebAssembly - 动态链接
- WebAssembly - 安全性
- WebAssembly - 使用 C 语言
- WebAssembly - 使用 C++
- WebAssembly - 使用 Rust
- WebAssembly - 使用 Go
- WebAssembly - 使用 Nodejs
- WebAssembly - 示例
- WebAssembly 有用资源
- WebAssembly 快速指南
- WebAssembly - 有用资源
- WebAssembly - 讨论
WebAssembly 快速指南
WebAssembly - 概述
WebAssembly 是一种用于 Web 的新型计算机编程语言。WebAssembly 代码是一种低级二进制格式,与 Web 兼容,并且可以轻松地在现代 Web 浏览器中运行。生成的文件大小很小,并且加载和执行速度更快。您现在可以将 C、C++、Rust 等语言编译为二进制格式,并且它可以在 Web 上像 javascript 一样运行。
WebAssembly 的定义
根据 WebAssembly 的官方网站(可在 https://webassembly.net.cn/ 获取),其定义为 WebAssembly(缩写为 Wasm)是一种基于栈的虚拟机的二进制指令格式。Wasm 被设计为 C/C++/Rust 等高级语言的便携式编译目标,使客户端和服务器应用程序能够在 Web 上部署。
Web Assembly 不是开发人员必须编写的语言,而是用 C、C++、Rust 等语言编写的代码,可以编译成 WebAssembly (wasm)。相同的代码可以在 Web 浏览器内部运行。
Web Assembly 是一种新的语言,代码是低级汇编语言,但凭借其文本格式功能,代码具有可读性,并且如果需要,可以进行调试。
WebAssembly 的目标
WebAssembly 的开放标准是在一个 W3C 社区小组中开发的,该小组包括来自所有主要浏览器的代表以及一个 W3C 工作组。
WebAssembly 的主要目标如下所示 -
更快、高效且可移植 - WebAssembly 代码旨在利用可用的硬件在不同的平台上更快地运行。
易于阅读和调试 - WebAssembly 作为一种低级汇编语言,支持文本格式,允许您调试代码中的任何问题,并在必要时重写代码。
安全性 - WebAssembly 在 Web 浏览器上运行是安全的,因为它会处理权限和同源策略。
WebAssembly 的优势
以下是 WebAssembly 的优势 -
在现代浏览器上运行 - WebAssembly 能够在可用的现代 Web 浏览器上毫无问题地执行。
支持多种语言 - C、C++、Rust、Go 等语言现在可以将代码编译为 WebAssembly,并在 Web 浏览器中运行。因此,以前无法在浏览器中运行的语言现在可以实现了。
更快、高效且可移植 - 由于代码体积小,因此加载和执行速度更快。
易于理解 - 开发人员不必花费太多精力来理解 WebAssembly 编码,因为他们不必用 WebAssembly 编写代码。而是将代码编译为 WebAssembly,并在 Web 上执行。
易于调试 - 尽管最终代码是低级汇编语言,但您也可以将其获取为易于阅读和调试的文本格式。
WebAssembly 的缺点
以下是 WebAssembly 的缺点 -
WebAssembly 仍在开发中,现在就断言其未来还为时过早。
WebAssembly 依赖于 javascript 与文档对象模型 (DOM) 进行交互。
WebAssembly - 简介
WebAssembly 也称为 WASM,于 2017 年首次推出。WebAssembly 起源背后的主要科技公司包括 Google、Apple、Microsoft、Mozilla 和 W3C。
坊间传闻称 WebAssembly 由于其更快的执行速度将取代 Javascript,但事实并非如此。WebAssembly 和 Javascript 旨在协同工作以解决复杂问题。
WebAssembly 的需求
到目前为止,只有 Javascript 可以在浏览器内部成功工作。浏览器中有一些非常繁重的任务难以使用 javascript 执行。
举几个例子,例如图像识别、计算机辅助设计 (CAD) 应用程序、实时视频增强、VR 和增强现实、音乐应用程序、科学可视化和模拟、游戏、图像/视频编辑等。
WebAssembly 是一种具有二进制指令的新语言,可以更快地加载和执行。上述任务可以使用 C、C++、Rust 等高级语言轻松完成。我们需要一种方法,将我们用 C、C++、Rust 编写的代码编译并用于 Web 浏览器。使用 WebAssembly 可以实现这一点。
当 WebAssembly 代码加载到浏览器内部时。然后,浏览器负责将其转换为处理器可以理解的机器格式。
对于 javascript,代码必须下载、解析并转换为机器格式。这需要花费大量时间,对于我们之前提到的繁重任务来说,速度可能会非常慢。
WebAssembly 的工作原理
像 C、C++ 和 Rust 这样的高级语言被编译成二进制格式,即 .wasm 和文本格式 .wat。
用 C、C++ 和 Rust 编写的源代码使用编译器编译为 .wasm。您可以使用 Emscripten SDK 将 C/C++ 编译为 .wasm。
流程如下 -
可以使用 Emscripten SDK 将 C/C++ 代码编译为 .wasm。随后,可以在 html 文件中借助 javascript 使用 .wasm 代码来显示输出。
WebAssembly 的关键概念
关键概念解释如下 -
模块
模块是由浏览器编译为可执行机器代码的对象。模块被认为是无状态的,可以在窗口和 Web 工作线程之间共享。
内存
WebAssembly 中的内存是一个arraybuffer,用于保存数据。您可以使用 Javascript api WebAssembly.memory() 分配内存。
表
WebAssembly 中的表是一个类型化数组,即 WebAssembly 内存外部,并且主要包含对函数的引用。它存储函数的内存地址。
实例
实例是一个对象,它将包含所有可以从 javascript 调用的导出函数,以便在浏览器中执行。
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/ 获取)获取如下所示的编译代码 -
阶乘程序的 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 代码,就像下面提到的那样 -
开发人员不应该用 wasm 编写代码或学习用它编写代码,因为它主要是在编译高级语言时生成的。
栈式机器模型
在 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 执行。
执行期间将两个数字相加的栈表示如下 -
在步骤 1中 - 执行 get_local $a 指令,第一个参数即 $a 被推送到栈上。
在步骤 2中 - 在执行 get_local $b 指令期间,第二个参数即 $b 被推送到栈上。
在步骤 3中 - i32.add 的执行将从栈中弹出元素,并将结果推回栈上。最后栈中保留的值是函数 $add 的结果。
WebAssembly - 安装
在本节中,我们将学习如何安装 Emscripten SDK 来编译 C/C++。Emscripten 是一种低级虚拟机 (LLVM),它接收从 C/C++ 生成的字节码并将其编译成可以轻松地在浏览器中执行的 JavaScript。
要将 C/C++ 编译为 WebAssembly,我们首先需要安装 Emscripten sdk。
安装 Emscripten sdk
安装 Emscripten sdk 的步骤如下 -
步骤 1 - 克隆 emsdk 仓库:git clone https://github.com/emscripten-core/emsdk.git。
E:\wa>git clone https://github.com/emscripten-core/emsdk.git Cloning into 'emsdk'... remote: Enumerating objects: 14, done. remote: Counting objects: 100% (14/14), done. remote: Compressing objects: 100% (12/12), done. remote: Total 1823 (delta 4), reused 4 (delta 2), pack-reused 1809 receiving obje cts: 99% (1819/1823), 924.01 KiB | 257.00 KiB/s Receiving objects: 100% (1823/1823), 1.01 MiB | 257.00 KiB/s, done. Resolving deltas: 100% (1152/1152), done.
步骤 2 - 进入 emsdk 目录。
cd emsdk
步骤 3 - 对于 Windows:执行以下命令。
emsdk install latest
对于 Linux,此命令将花费一些时间来安装必要的工具,例如 java、python 等。请遵循以下代码 -
./emsdk install latest
步骤 4 - 要激活最新的 SDK,请在终端中执行以下命令。
对于 Windows,执行以下命令 -
emsdk activate latest
对于 Linux,执行以下命令 -
./emsdk activate latest
步骤 5 - 要激活 PATH 和其他环境变量,请在终端中运行以下命令。
对于 Windows,执行命令 -
emsdk_env.bat
对于 Linux,执行以下命令 -
source ./emsdk_env.sh
我们已经完成了 emsdk 的安装,现在可以编译 C 或 C++ 代码了。C/C++ 的编译将在后面的章节中进行。
要编译任何 C 或 C++ 代码,以下为命令 -
emcc source.c or source.cpp -s WASM=1 -o source.html
输出将为您提供 source.html 文件、source.js 和 source.wasm 文件。js 将包含用于获取 source.wasm 的 api,当您在浏览器中点击 source.html 时,您可以看到输出。
要仅获取 wasm 文件,可以使用以下命令。此命令将仅为您提供 source.wasm 文件。
emcc source.c or source.cpp -s STANDALONE_WASM
WebAssembly - 编译为 WASM 的工具
本章将讨论一些易于使用的工具,这些工具在使用 WebAssembly 时非常有用。让我们从学习 WebAssembly.studio 工具开始。
WebAssembly.studio
此工具允许您将 C、Rust、Wat 编译为 Wasm 等。
首先,您可以点击 Empty C Project、Empty Rust Project、Empty Wat Project 将 C 和 Rust 编译为 WASM。5。
它具有 Build、Run 功能,用于构建代码并检查输出。下载按钮允许您下载.wasm文件,该文件可用于在浏览器中进行测试。此工具非常有助于编译 C 和 Rust 代码并检查输出。
WebAssembly Explorer
WebAssembly Explorer 允许您编译 C 和 C++ 代码。有关更多详细信息,请参阅链接 https://mbebenita.github.io/WasmExplorer/。点击链接后将显示如下屏幕 -
您可以选择 C 和 C++ 版本。C 或 C++ 的源代码在此处编写 -
点击 Compile 按钮后,它会在下面的块中给出 WebAssembly 文本格式 (WAT) 和 Firefox x86 汇编代码 -
您可以下载.wasm代码并在浏览器中进行测试。
WASMFiddle
Wasmfiddle 帮助你将 C 代码编译成 WebAssembly,并测试输出结果。点击链接 https://wasmfiddle.com/ 后,你将看到以下页面:
点击“构建”来编译代码。你可以点击“Wat”和“Wasm”来下载 Wat 和 Wasm 代码。要测试输出结果,请点击“运行”按钮。
WASM 到 WAT
工具 **wat2wasm** 会在你输入 WebAssembly 文本格式时生成 wasm 代码。你可以点击链接 https://github.webassembly.net.cn/wabt/demo/wat2wasm/ 查看演示,出现的屏幕如下所示:
你可以使用上传按钮上传 .wasm 文件,文本区域将显示文本格式。
WAT 到 WASM
工具 wat2wasm 会在你输入 WebAssembly 文本格式时生成 wasm 代码。你可以点击链接 https://github.webassembly.net.cn/wabt/demo/wat2wasm/ 查看演示,出现的屏幕如下所示:
这个工具非常有用,因为它可以帮助你获得并测试输出结果。你可以输入 WAT 代码,查看 .wasm 代码,并执行代码以查看输出。
WebAssembly - 程序结构
WebAssembly,也称为 WASM,是一种二进制格式的低级代码,旨在以最有效的方式在浏览器中执行。WebAssembly 代码由以下概念构成:
- 值
- 类型
- 指令
让我们详细了解一下。
值
WebAssembly 中的值用于存储复杂数据,例如文本、字符串和向量。WebAssembly 支持以下类型:
- 字节
- 整数
- 浮点数
- 名称
字节
字节是 WebAssembly 支持的最简单形式的值。值采用十六进制格式。
例如表示为 *b* 的字节,也可以取自然数 n,其中 n < 256。
byte ::= 0x00| .... |0xFF
整数
在 WebAssembly 中,支持的整数如下所示:
- i32:32 位整数
- i64:64 位整数
浮点数
在 WebAssembly 中,支持的浮点数如下所示:
- f32:32 位浮点数
- f64:64 位浮点数
名称
名称是字符序列,其标量值由 Unicode 定义,可以在此处提供的链接 http://www.unicode.org/versions/Unicode12.1.0/ 中找到。
类型
WebAssembly 中的实体被分类为类型。支持的类型如下所示:
- 值类型
- 结果类型
- 函数类型
- 限制
- 内存类型
- 表类型
- 全局类型
- 外部类型
让我们逐一学习它们。
值类型
WebAssembly 支持的值类型如下所示:
- i32:32 位整数
- i64:64 位整数
- f32:32 位浮点数
- f64:64 位浮点数
valtype ::= i32|i64|f32|f64
结果类型
括号内编写的值会被执行并存储在结果类型中。结果类型是代码块(由值组成)执行的输出。
resulttype::=[valtype?]
函数类型
函数类型将接收参数向量并返回结果向量。
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 代码是一系列遵循堆栈机器模型的指令。由于 WebAssembly 遵循堆栈机器模型,因此指令会被压入堆栈。
例如,函数的参数值会从堆栈中弹出,结果会被压回堆栈。最终,堆栈中只有一个值,即结果。
一些常用的指令如下所示:
- 数值指令
- 变量指令
数值指令
数值指令是对数值执行的操作。
例如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
变量指令
变量指令与访问局部变量和全局变量有关。
例如
访问局部变量:
get_local $a get_local $b
设置局部变量:
set_local $a set_local $b
访问全局变量:
get_global $a get_global $b
设置全局变量:
set_global $a set_global $b
WebAssembly - JavaScript
本章将列出 WebAssembly 和 Javascript 之间的比较。
Javascript 是一种我们在浏览器中大量使用的语言。现在,随着 WebAssembly 的发布,我们也可以在浏览器中使用 WebAssembly。
WebAssembly 的出现并非为了取代 javascript,而是为了处理 javascript 难以处理的某些事情。
例如
使用 javascript 难以完成图像识别、CAD 应用、实时视频增强、VR 和增强现实、音乐应用、科学可视化和模拟、游戏、图像/视频编辑等任务。
使用现在可以编译成 WebAssembly 的高级语言(如 C/C++、Rust),可以轻松完成上述任务。WebAssembly 生成易于在浏览器中执行的二进制代码。
因此,以下是 Javascript 和 WebAssembly 之间的比较列表。
参数 | Javascript | WebAssembly |
---|---|---|
编码 |
你可以轻松地用 Javascript 编写代码。编写的代码是人类可读的,并保存为 .js 文件。在浏览器中使用时,你需要使用 ` |