
- 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.org/ 獲取),其定義為 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://webassembly.github.io/wabt/demo/wat2wasm/ 檢視演示,出現的螢幕如下所示:

你可以使用上傳按鈕上傳 .wasm 檔案,文字區域將顯示文字格式。
WAT 到 WASM
工具 wat2wasm 會在你輸入 WebAssembly 文字格式時生成 wasm 程式碼。你可以點選連結 https://webassembly.github.io/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 檔案。在瀏覽器中使用時,你需要使用 ` |