WebAssembly - Hướng dẫn nhanh
WebAssembly là một ngôn ngữ lập trình máy tính mới cho web. Mã WebAssembly là một định dạng nhị phân cấp thấp, tương thích với web và có thể dễ dàng chạy trong các trình duyệt web hiện đại. Kích thước tệp được tạo nhỏ và nó tải và thực thi nhanh hơn. Bây giờ bạn có thể biên dịch các ngôn ngữ như C, C ++, Rust, v.v. sang định dạng nhị phân và nó có thể chạy trên web giống như javascript.
Định nghĩa của WebAssembly
Theo trang web chính thức của WebAssembly, có sẵn tại https://webassembly.org/, nó được định nghĩa là WebAssembly (viết tắt là Wasm) là một định dạng lệnh nhị phân cho một máy ảo dựa trên ngăn xếp. Wasm được thiết kế như một mục tiêu di động để biên dịch các ngôn ngữ cấp cao như C / C ++ / Rust, cho phép triển khai trên web cho các ứng dụng máy khách và máy chủ.
Web Assembly không phải là thứ mà một nhà phát triển sẽ phải viết, nhưng mã được viết bằng các ngôn ngữ như C, C ++, Rust và có thể được biên dịch sang WebAssembly (wasm). Mã tương tự có thể được chạy bên trong trình duyệt web.
Web Assembly là một ngôn ngữ mới, mã là ngôn ngữ hợp ngữ cấp thấp, nhưng với tính năng định dạng văn bản, mã có thể đọc được và có thể gỡ lỗi nếu cần.
Mục tiêu của WebAssembly
Các tiêu chuẩn mở cho WebAssembly được phát triển trong Nhóm cộng đồng W3C bao gồm các đại diện từ tất cả các trình duyệt chính cũng như Nhóm làm việc W3C.
Các mục tiêu chính của WebAssembly được đề cập dưới đây:
Faster, Efficient and Portable - Mã WebAssembly có nghĩa là chạy nhanh hơn trên các nền tảng khác nhau tận dụng lợi thế của phần cứng có sẵn.
Easy to read and debug - WebAssembly, là một ngôn ngữ hợp ngữ cấp thấp, có hỗ trợ định dạng văn bản, cho phép bạn gỡ lỗi mã cho bất kỳ sự cố nào và cũng có thể viết lại mã, nếu cần.
Security - WebAssembly an toàn khi chạy trên trình duyệt web, vì nó quản lý các quyền và chính sách nguồn gốc.
Ưu điểm của WebAssembly
Sau đây là những ưu điểm của WebAssembly:
Run is Modern Browsers - WebAssembly có thể thực thi mà không gặp bất kỳ sự cố nào trên các trình duyệt web hiện đại có sẵn.
Multiple Language support- Các ngôn ngữ như C, C ++, Rust, Go giờ đây có thể biên dịch mã sang WebAssembly và chạy tương tự trong các trình duyệt web. Vì vậy, các ngôn ngữ không thể chạy trong trình duyệt giờ đây sẽ có thể làm như vậy.
Faster, Efficient and Portable - Do kích thước nhỏ của mã, nó tải và thực thi nhanh hơn.
Easy to understand- Các nhà phát triển không phải căng thẳng trong việc hiểu mã WebAssembly, vì họ không phải viết mã trong WebAssembly. Thay vào đó, hãy biên dịch mã trong WebAssembly và thực thi tương tự trên web.
Easy to Debug - Mặc dù mã cuối cùng ở dạng hợp ngữ cấp thấp, bạn cũng có thể lấy nó ở định dạng văn bản, dễ đọc và gỡ lỗi.
Nhược điểm của WebAssembly
Sau đây là những nhược điểm của WebAssembly:
WebAssembly vẫn đang được nghiên cứu và còn quá sớm để quyết định tương lai của nó.
WebAssembly phụ thuộc vào javascript để tương tác với Mô hình đối tượng tài liệu (DOM).
WebAssembly còn được gọi là WASM được giới thiệu lần đầu tiên vào năm 2017. Các công ty công nghệ lớn đứng sau nguồn gốc của WebAssembly là Google, Apple, Microsoft, Mozilla và W3C.
Điểm đáng chú ý là WebAssembly sẽ thay thế Javascript vì nó thực thi nhanh hơn, nhưng không phải vậy. WebAssembly và Javascript có nghĩa là làm việc cùng nhau để giải quyết các vấn đề phức tạp.
Cần cho WebAssembly
Cho đến nay, chúng tôi chỉ có Javascript có thể hoạt động thành công bên trong trình duyệt. Có những tác vụ rất nặng khó thực hiện trên trình duyệt sử dụng javascript.
Có thể kể tên một vài ứng dụng đó là Nhận dạng hình ảnh, Thiết kế có sự hỗ trợ của máy tính (CAD), Tăng video trực tiếp, VR và thực tế tăng cường, Ứng dụng âm nhạc, Hình ảnh hóa và mô phỏng khoa học, Trò chơi, Chỉnh sửa hình ảnh / video, v.v.
WebAssembly là một ngôn ngữ mới với lệnh nhị phân có thể tải và thực thi nhanh hơn. Nhiệm vụ được nêu ở trên, có thể dễ dàng được thực hiện bằng các ngôn ngữ cấp cao như C, C ++, Rust, v.v. Chúng ta cần một cách để mã chúng ta có trong C, C ++, Rust có thể được biên dịch và có thể sử dụng nó trong trình duyệt web. Điều này cũng có thể đạt được bằng cách sử dụng WebAssembly.
Khi mã WebAssembly được tải bên trong trình duyệt. Sau đó, trình duyệt sẽ chuyển đổi thành định dạng máy mà bộ xử lý có thể hiểu được.
Đối với javascript, mã phải được tải xuống, phân tích cú pháp và chuyển đổi sang định dạng máy. Rất nhiều thời gian dành cho nó và đối với các tác vụ nặng như chúng tôi đã đề cập trước đó có thể rất chậm.
Hoạt động của WebAssembly
Các ngôn ngữ cấp cao như C, C ++ và Rust được biên dịch thành định dạng nhị phân, nghĩa là .wasm và định dạng văn bản .wat.
Mã nguồn được viết bằng C, C ++ và Rust được biên dịch thành .wasmsử dụng trình biên dịch. Bạn có thể sử dụng SDK Emscripten để biên dịch C / C ++ sang.wasm.
Quy trình như sau:
Mã C / C ++ có thể được biên dịch thành .wasmsử dụng SDK Emscripten. Sau đó,.wasm mã có thể được sử dụng với sự trợ giúp của javascript trong tệp html của bạn để hiển thị đầu ra.
Các khái niệm chính về WebAssembly
Các khái niệm chính như được giải thích bên dưới:
Mô-đun
Mô-đun là một đối tượng được trình duyệt biên dịch thành mã máy thực thi. Một mô-đun được cho là không trạng thái và nó có thể được chia sẻ giữa windows và web worker.
Ký ức
Bộ nhớ trong WebAssembly, là một arraybuffergiữ dữ liệu. Bạn có thể cấp phát bộ nhớ bằng cách sử dụng Javascript api WebAssembly.memory ().
Bàn
Bảng trong WebAssembly là một mảng được nhập nằm ngoài bộ nhớ WebAssembly và chủ yếu có tham chiếu đến các hàm. Nó lưu trữ địa chỉ bộ nhớ của các chức năng.
Phiên bản
Instance là một đối tượng sẽ có, tất cả các hàm được xuất có thể được gọi từ javascript để thực thi bên trong trình duyệt.
WebAssembly còn được gọi là wasm, là một cải tiến của Javascript. Nó được thiết kế để chạy bên trong các trình duyệt giống như javascript và cả với nodejs. Bạn tình cờ nhận được đầu ra wasm, khi bất kỳ ngôn ngữ cấp cao nào như C, C ++, Rust được biên dịch.
Hãy xem xét chương trình C sau:
int factorial(int n) {
if (n == 0)
return 1;
else
return n * factorial(n-1);
}
Sử dụng WasmExplorer, có sẵn tạihttps://mbebenita.github.io/WasmExplorer/ để lấy mã đã biên dịch như hình dưới đây -
Định dạng văn bản WebAssembly cho chương trình giai thừa như được nêu dưới đây:
(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)
)
)
Sử dụng công cụ Wat2Wasm, bạn có thể xem mã WASM, giống như cách nó được đề cập bên dưới -
Các nhà phát triển không được phép viết mã bằng wasm hoặc học cách viết mã trong đó, vì nó chủ yếu được tạo ra khi bạn biên dịch các ngôn ngữ cấp cao.
Mô hình máy xếp chồng
Trong WASM, tất cả các lệnh được đẩy vào ngăn xếp. Các đối số được bật lên và kết quả được đẩy trở lại ngăn xếp.
Hãy xem xét định dạng Văn bản của WebAssembly sau đây có thêm 2 số -
(module
(func $add (param $a i32) (param $b i32) (result i32)
get_local $a get_local $b
i32.add
)
(export "add" (func $add))
)
Tên của hàm là $add, nó mất 2 params $a and $b. Kết quả là một kiểu số nguyên 32 bit. Các biến cục bộ được truy cập bằng get_local và hoạt động thêm được thực hiện bằng i32.add.
Biểu diễn ngăn xếp để thêm 2 số trong khi thực thi sẽ như sau:
Trong step 1 - Việc thực thi get_local $a instruction, the first parameters i.e., $a được đẩy vào ngăn xếp.
Trong step 2 - Trong quá trình thực thi get_local $b instruction, the second parameters i.e., $b được đẩy trên ngăn xếp.
Trong step 3- Việc thực thi i32.add sẽ bật các phần tử từ ngăn xếp và sẽ đẩy kết quả trở lại ngăn xếp. Giá trị cuối cùng bên trong ngăn xếp là kết quả của hàm $ add.
Trong chương này, sẽ học cách cài đặt Emscripten SDK để biên dịch C / C ++. Emscripten là một máy ảo cấp độ thấp (LLVM) lấy bytecode được tạo từ C / C ++ và biên dịch nó thành JavaScript có thể dễ dàng thực thi bên trong trình duyệt.
Để biên dịch C / C ++ sang WebAssembly, trước tiên chúng ta cần cài đặt Emscripten sdk.
Cài đặt sdk Emscripten
Các bước để cài đặt Emscripten sdk như sau:
Step 1 - Sao chép repo 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.
Step 2 - Nhập vào bên trong thư mục emsdk.
cd emsdk
Step 3 - Đối với windows: Thực hiện lệnh sau.
emsdk install latest
For linux, lệnh này sẽ mất một khoảng thời gian để cài đặt các công cụ cần thiết như java, python, v.v. Làm theo đoạn mã được đề cập bên dưới -
./emsdk install latest
Step 4 - Để kích hoạt SDK mới nhất, hãy thực hiện lệnh sau trong thiết bị đầu cuối của bạn.
For windows, thực hiện lệnh sau:
emsdk activate latest
For linux, thực hiện lệnh được đề cập bên dưới -
./emsdk activate latest
Step 5 - Để kích hoạt PATH và các biến môi trường khác, hãy chạy lệnh sau trong thiết bị đầu cuối của bạn.
For windows, thực hiện lệnh -
emsdk_env.bat
For linux, thực hiện lệnh sau:
source ./emsdk_env.sh
Chúng tôi đã cài đặt xong emsdk và bây giờ có thể biên dịch mã C hoặc C ++. Việc biên dịch C / C ++ sẽ được thực hiện trong các chương tiếp theo.
Để biên dịch bất kỳ mã C hoặc C ++ nào, sau đây là lệnh:
emcc source.c or source.cpp -s WASM=1 -o source.html
Đầu ra sẽ cung cấp cho bạn tệp source.html, tệp source.js và source.wasm. Js sẽ có api sẽ tìm nạp source.wasm và bạn có thể thấy đầu ra khi bạn nhấn source.html trong trình duyệt.
Để chỉ lấy tập tin wasm, bạn có thể sử dụng lệnh sau. Lệnh này sẽ chỉ cung cấp cho bạn tệp source.wasm.
emcc source.c or source.cpp -s STANDALONE_WASM
Chương này sẽ thảo luận về một số công cụ dễ sử dụng rất hữu ích khi làm việc với WebAssembly. Chúng ta hãy bắt đầu bằng cách tìm hiểu về công cụ WebAssembly.studio.
WebAssembly.studio
Công cụ này cho phép bạn biên dịch C, Rust, Wat thành Wasm, v.v.
Để bắt đầu, bạn có thể nhấp vào Empty C Project, Empty Rust Project, Empty Wat Project để biên dịch C và Rust sang WASM. 5.
Nó có Build, Run để xây dựng mã và kiểm tra đầu ra. Nút tải xuống cho phép bạn tải xuống.wasm, có thể được sử dụng để kiểm tra bên trong trình duyệt. Công cụ này rất hữu ích để biên dịch mã C và Rust và kiểm tra đầu ra.
WebAssembly Explorer
WebAssembly Explorer cho phép bạn biên dịch mã C và C ++. Tham khảo liên kếthttps://mbebenita.github.io/WasmExplorer/để biết thêm chi tiết. Màn hình sẽ xuất hiện sau khi nhấp vào liên kết được hiển thị bên dưới -
Bạn có thể chọn phiên bản C và C ++. Mã nguồn của C hoặc C ++ được viết ở đây:
Khi bạn nhấp vào nút Biên dịch, nó sẽ đưa ra định dạng văn bản WebAssembly (WAT) và mã Assembly Firefox x86 trong các khối bên dưới -
Bạn có thể tải xuống .wasm mã để kiểm tra nó bên trong trình duyệt.
WASMFiddle
Wasmfiddle giúp bạn biên dịch mã C sang WebAssembly và cũng kiểm tra đầu ra. Sau khi nhấp vào liên kếthttps://wasdk.github.io/WasmFiddle/, bạn sẽ thấy trang sau -
Nhấp vào Xây dựng để biên dịch mã. Bạn có thể tải xuống mã Wat và Wasm bằng cách nhấp vào Wat và Wasm. Để kiểm tra đầu ra, hãy nhấp vào nút Run.
WASM để XEM
Công cụ wat2wasmsẽ cung cấp cho bạn mã wasm khi bạn nhập định dạng văn bản WebAssembly. Bạn có thể nhấp vào liên kếthttps://webassembly.github.io/wabt/demo/wat2wasm/ cho bản demo và màn hình sẽ xuất hiện được đưa ra bên dưới:
Bạn có thể sử dụng nút tải lên để tải lên .wasm và textarea sẽ hiển thị định dạng văn bản.
WAT thành WASM
Công cụ wat2wasm sẽ cung cấp cho bạn mã wasm khi bạn nhập định dạng văn bản WebAssembly. Bạn có thể nhấp vào liên kếthttps://webassembly.github.io/wabt/demo/wat2wasm/ cho bản demo và màn hình sẽ xuất hiện được đưa ra bên dưới:
Công cụ này rất hữu ích, vì nó giúp kiểm tra đầu ra. Bạn có thể nhập mã WAT và xem mã .wasm và cũng thực thi mã để xem kết quả.
WebAssembly, còn được gọi là WASM, là mã cấp thấp định dạng nhị phân được phát triển để thực thi bên trong trình duyệt theo cách hiệu quả nhất. Mã WebAssembly được cấu trúc với các khái niệm sau:
- Values
- Types
- Instructions
Hãy cùng chúng tôi tìm hiểu chi tiết chúng ngay bây giờ.
Giá trị
Giá trị trong WebAssembly có nghĩa là để lưu trữ dữ liệu phức tạp như văn bản, chuỗi và vectơ. WebAssembly hỗ trợ những điều sau:
- Bytes
- Integers
- Dấu chấm động
- Names
Byte
Byte là dạng giá trị đơn giản nhất được hỗ trợ trong WebAssembly. Giá trị ở định dạng thập lục phân.
For exampleCác byte được biểu diễn dưới dạng b , cũng có thể nhận số tự nhiên n, trong đó n <256.
byte ::= 0x00| .... |0xFF
Số nguyên
Trong WebAssembly, các số nguyên được hỗ trợ như dưới đây:
- i32: số nguyên 32 bit
- i64: số nguyên 64 bit
Dấu chấm động
Trong WebAssembly, số dấu phẩy động được hỗ trợ như sau:
- f32: 32-bit dấu phẩy động
- f64: dấu chấm động 64 bit
Tên
Tên là chuỗi ký tự, với các giá trị vô hướng được xác định bởi Unicode, có sẵn tại liên kết http://www.unicode.org/versions/Unicode12.1.0/ đưa ra kèm theo đây.
Các loại
Các thực thể trong WebAssembly được phân loại thành các loại. Các loại được hỗ trợ như được nêu bên dưới -
- Các loại giá trị
- Các loại kết quả
- Các loại chức năng
- Limits
- Các loại bộ nhớ
- Các loại bảng
- Các loại toàn cầu
- Các loại bên ngoài
Hãy để chúng tôi nghiên cứu chúng từng cái một.
Các loại giá trị
Loại giá trị được WebAssembly hỗ trợ như được đề cập bên dưới:
- i32: số nguyên 32 bit
- i64: số nguyên 64 bit
- f32: 32-bit dấu phẩy động
- f64: dấu chấm động 64 bit
valtype ::= i32|i64|f32|f64
Các loại kết quả
Các giá trị được viết bên trong dấu ngoặc được thực thi và lưu trữ bên trong các kiểu kết quả. Kiểu kết quả là đầu ra của việc thực thi một khối mã được tạo thành từ các giá trị.
resulttype::=[valtype?]
Các loại chức năng
Một kiểu hàm sẽ nhận vectơ tham số trả về một vectơ kết quả.
functype::=[vec(valtype)]--> [vec(valtype)]
Hạn mức
Giới hạn là phạm vi lưu trữ được liên kết với bộ nhớ và loại bảng.
limits ::= {min u32, max u32}
Các loại bộ nhớ
Các loại bộ nhớ xử lý các bộ nhớ tuyến tính và phạm vi kích thước.
memtype ::= limits
Các loại bảng
Loại bảng được phân loại theo loại phần tử được gán cho nó.
tabletype ::= limits elemtype
elemtype ::= funcref
Loại bảng phụ thuộc vào giới hạn cho kích thước tối thiểu và tối đa được gán cho nó.
Các loại toàn cầu
Global Type chứa các biến toàn cục có giá trị có thể thay đổi hoặc giữ nguyên.
globaltype ::= mut valtype
mut ::= const|var
Các loại bên ngoài
Loại bên ngoài đề cập đến nhập khẩu và giá trị bên ngoài
externtype ::= func functype | table tabletype | mem memtype | global globaltype
Hướng dẫn
Mã WebAssembly là một chuỗi hướng dẫn tuân theo mô hình máy xếp. Vì WebAssembly theo mô hình máy ngăn xếp nên các hướng dẫn được đẩy lên ngăn xếp.
Ví dụ, các giá trị đối số cho một hàm được bật ra từ ngăn xếp và kết quả được đẩy trở lại ngăn xếp. Cuối cùng, sẽ chỉ có một giá trị trong ngăn xếp và đó là kết quả.
Một số Hướng dẫn thường được sử dụng như sau:
- Hướng dẫn số
- Hướng dẫn biến
Hướng dẫn số
Hướng dẫn số là các hoạt động được thực hiện trên giá trị số.
For examplenn, 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
Hướng dẫn biến
Hướng dẫn biến là về cách truy cập các biến cục bộ và toàn cục.
For example
Để truy cập các biến cục bộ -
get_local $a
get_local $b
Đến set biến cục bộ -
set_local $a
set_local $b
Đến access biến toàn cục -
get_global $a
get_global $b
Đến set biến toàn cục -
set_global $a
set_global $b
Chương này sẽ liệt kê sự so sánh giữa WebAssembly và Javascript.
Javascript là một ngôn ngữ mà chúng ta đã sử dụng rất nhiều bên trong trình duyệt. Giờ đây, với bản phát hành WebAssembly, chúng ta cũng có thể sử dụng WebAssembly bên trong trình duyệt.
Lý do để WebAssembly ra đời không phải để thay thế javascript mà là để giải quyết một số thứ khó xử lý với javascript.
For example
Rất khó để thực hiện các tác vụ như Nhận dạng hình ảnh, ứng dụng CAD, Tăng video trực tiếp, VR và thực tế tăng cường, Ứng dụng âm nhạc, Hình ảnh hóa và mô phỏng khoa học, Trò chơi, Chỉnh sửa hình ảnh / video, v.v. bằng javascript.
Sử dụng các ngôn ngữ cấp cao như C / C ++, Rust, hiện có thể được biên dịch sang WebAssembly, thật dễ dàng để hoàn thành nhiệm vụ nêu trên. WebAssembly tạo ra một mã nhị phân dễ thực thi bên trong trình duyệt.
Đây là danh sách so sánh được thực hiện giữa Javascript và WebAssembly.
Thông số | Javascript | WebAssembly |
---|---|---|
Mã hóa |
Bạn có thể dễ dàng viết mã bằng Javascript. Mã được viết là con người có thể đọc được và được lưu dưới dạng .js. Khi sử dụng bên trong trình duyệt, bạn cần sử dụng thẻ <script>. |
Mã có thể được viết ở định dạng văn bản trong WebAssembly và nó được lưu dưới dạng .wat. Rất khó để viết mã ở định dạng .wat. Tốt nhất là biên dịch mã từ một số ngôn ngữ cấp cao khác thay vì viết từ đầu bằng .wat. Bạn không thể thực thi tệp .wat bên trong trình duyệt và phải chuyển đổi thành .wasm bằng trình biên dịch hoặc các công cụ trực tuyến có sẵn. |
Chấp hành |
Mã được viết bằng javascript khi được sử dụng bên trong trình duyệt phải được tải xuống, phân tích cú pháp, biên dịch và tối ưu hóa. |
Chúng tôi có mã WebAssembly ở dạng .wasm đã được biên dịch và ở định dạng nhị phân. |
Quản lý bộ nhớ |
Javascript chỉ định bộ nhớ khi, các biến được tạo và bộ nhớ được giải phóng khi không được sử dụng và được thêm vào bộ sưu tập rác. |
Bộ nhớ trong WebAssembly là một bộ đệm mảng lưu trữ dữ liệu. Bạn có thể cấp phát bộ nhớ bằng cách sử dụng API Javascript WebAssembly.memory (). Bộ nhớ WebAssembly được lưu trữ ở định dạng mảng, tức là một mô hình bộ nhớ phẳng dễ hiểu và dễ thực hiện. Nhược điểm của mô hình bộ nhớ trong WebAssembly là -
|
Thời gian tải & hiệu suất |
Trong trường hợp javascript, khi được gọi bên trong trình duyệt, tệp javascript phải được tải xuống và phân tích cú pháp. Sau đó, trình phân tích cú pháp chuyển đổi mã nguồn thành mã bytecode mà công cụ javascript thực thi mã trong trình duyệt. Công cụ Javascript rất mạnh mẽ và do đó, thời gian tải và hiệu suất của javascript rất nhanh so với WebAssembly. |
Mục tiêu quan trọng nhất của WebAssembly là nhanh hơn JavaScript. Mã chất liệu được tạo từ các ngôn ngữ cấp cao có kích thước nhỏ hơn và do đó, thời gian tải nhanh hơn. Tuy nhiên, các ngôn ngữ như GO, khi được biên dịch sang wasm sẽ tạo ra kích thước tệp lớn cho một đoạn mã nhỏ. WebAssembly được thiết kế theo cách biên dịch nhanh hơn và có thể chạy trên tất cả các trình duyệt chính. WebAssembly vẫn phải thêm nhiều cải tiến về mặt hiệu suất so với javascript. |
Gỡ lỗi |
Javascript là con người có thể đọc được và có thể được gỡ lỗi dễ dàng. Thêm các điểm ngắt vào mã javascript của bạn bên trong trình duyệt cho phép bạn dễ dàng gỡ lỗi mã. |
WebAssembly cung cấp mã ở định dạng văn bản, có thể đọc được nhưng vẫn rất khó gỡ lỗi. Firefox cho phép bạn xem mã wasm ở định dạng .wat bên trong trình duyệt. Bạn không thể thêm các điểm ngắt trong .wat và đó là thứ sẽ có trong tương lai. |
Hỗ trợ trình duyệt |
Javascript hoạt động tốt trên tất cả các trình duyệt. |
Tất cả các trình duyệt web chính đều có hỗ trợ WebAssembly. |
Trong chương này, chúng ta sẽ hiểu cách tải mã wasm và thực thi chúng trong trình duyệt bằng cách sử dụng sự trợ giúp của API webassembly javascript.
Dưới đây là một số API quan trọng, chúng tôi sẽ sử dụng trong suốt hướng dẫn để thực thi mã wasm.
- API trình duyệt fetch ()
- WebAssembly.compile
- WebAssembly.instance
- WebAssembly.instantiate
- WebAssembly.instantiateStreaming
Trước khi chúng ta thảo luận về API javascript của WebAssembly, để kiểm tra API và kết quả đầu ra, chúng ta sẽ sử dụng chương trình C sau đây và mã .wasm được tạo từ chương trình c bằng cách sử dụng wasm explorer.
Một ví dụ cho Chương trình C như sau:
#include<stdio.h>
int square(int n) {
return n*n;
}
Chúng tôi sẽ sử dụng WASM explorer, để lấy mã wasm -
Tải xuống mã WASM và sử dụng nó để kiểm tra API.
API trình duyệt fetch ()
API fetch () có nghĩa là để tải tài nguyên mạng .wasm.
<script>
var result = fetch("findsquare.wasm");
console.log(result);
</script>
Nó trả về một lời hứa như hình dưới đây -
Bạn cũng có thể sử dụng phương thức XMLHttpRequest để tìm nạp tài nguyên mạng wasm.
WebAssembly.compile ()
Trách nhiệm của api là biên dịch chi tiết mô-đun được lấy từ .wasm.
Cú pháp
Cú pháp như dưới đây:
WebAssembly.compile(buffer);
Thông số
Buffer - Mã này từ .wasm phải được chuyển đổi thành một mảng đã nhập hoặc bộ đệm mảng, trước khi đưa ra làm đầu vào để biên dịch.
Giá trị trả lại
Nó sẽ trả về một lời hứa sẽ có mô-đun được biên dịch.
Thí dụ
Hãy để chúng tôi xem một ví dụ, cung cấp đầu ra dưới dạng mô-đun được biên dịch bằng cách sử dụng webAssembly.compile ().
<script>
fetch("findsquare.wasm") .then(bytes => bytes.arrayBuffer())
.then(mod => {
var compiledmod = WebAssembly.compile(mod);
compiledmod.then(test=> {
console.log(test);
})
})
</script>
Đầu ra
Console.log, khi được chọn trong trình duyệt, sẽ cung cấp cho bạn chi tiết mô-đun đã biên dịch -
Mô-đun có một đối tượng phương thức khởi tạo với nhập, xuất và các tùy chỉnh. Hãy để chúng tôi xem API tiếp theo, để biết thêm chi tiết về mô-đun đã biên dịch.
WebAssembly.instance
Sử dụng WebAssembly.instance, API sẽ cung cấp cho bạn phiên bản thực thi của mô-đun đã biên dịch có thể được thực thi thêm để lấy đầu ra.
Cú pháp
Cú pháp như dưới đây:
new WebAssembly.Instance(compiled module)
Giá trị trả lại
Giá trị trả về sẽ là một đối tượng với hàm mảng xuất có thể được thực thi.
Thí dụ
<script>
fetch("findsquare.wasm")
.then(bytes => bytes.arrayBuffer())
.then(mod => WebAssembly.compile(mod)).then(module => {
let instance = new WebAssembly.Instance(module);
console.log(instance);
})
</script>
Đầu ra
Kết quả đầu ra sẽ cung cấp cho chúng ta một mảng hàm xuất như hình dưới đây:
Bạn có thể thấy hàm bình phương, mà chúng tôi nhận được từ mã C được biên dịch.
Để thực hiện hàm vuông, bạn có thể làm như sau:
<script>
fetch("findsquare.wasm")
.then(bytes => bytes.arrayBuffer())
.then(mod => WebAssembly.compile(mod))
.then(module => {
let instance = new WebAssembly.Instance(module);
console.log(instance.exports.square(15));
})
</script>
Đầu ra sẽ là -
225
WebAssembly.instantiate
API này đảm nhận việc biên dịch và khởi tạo mô-đun cùng nhau.
Cú pháp
Cú pháp như sau:
WebAssembly.instantiate(arraybuffer, importObject)
Thông số
arraybuffer - Mã từ .wasm phải được chuyển đổi thành mảng đã nhập hoặc bộ đệm mảng trước khi đưa ra làm đầu vào để khởi tạo.
importObject- Đối tượng nhập phải có thông tin chi tiết về bộ nhớ, các chức năng được nhập để sử dụng bên trong mô-đun. Nó có thể là một đối tượng mô-đun trống, trong trường hợp, không có gì để chia sẻ.
Giá trị trả lại
Nó sẽ trả về một lời hứa, sẽ có chi tiết mô-đun và phiên bản.
Thí dụ
<script type="text/javascript">
const importObj = {
module: {}
};
fetch("findsquare.wasm")
.then(bytes => bytes.arrayBuffer())
.then(module => WebAssembly.instantiate(module, importObj))
.then(finalcode => {
console.log(finalcode); console.log(finalcode.instance.exports.square(25));
});
</script>
Đầu ra
Khi bạn thực thi mã, bạn sẽ nhận được đầu ra được đề cập bên dưới.
WebAssembly.instantiateStreaming
API này đảm nhận việc biên dịch cũng như khởi tạo mô-đun WebAssembly từ mã .wasm được cung cấp.
Cú pháp
Cú pháp như dưới đây:
WebAssembly.instantiateStreaming(wasmcode, importObject);
Thông số
wasmcode - Phản hồi từ tìm nạp hoặc bất kỳ API nào khác cung cấp mã wasm và trả về một lời hứa.
importObject- Đối tượng nhập phải có thông tin chi tiết về bộ nhớ, các chức năng được nhập để sử dụng bên trong mô-đun. Nó có thể là một đối tượng mô-đun trống trong trường hợp không có gì để chia sẻ.
Giá trị trả lại
Nó sẽ trả về một lời hứa, sẽ có chi tiết mô-đun và phiên bản.
Thí dụ
Một ví dụ được thảo luận dưới đây -
<script type="text/javascript">
const importObj = {
module: {}
};
WebAssembly.instantiateStreaming(fetch("findsquare.wasm"), importObj).then(obj => {
console.log(obj);
});
</script>
Khi bạn kiểm tra nó trong trình duyệt, bạn sẽ thấy một lỗi -
Để làm cho nó hoạt động ở đầu máy chủ của bạn, bạn sẽ phải thêm ứng dụng loại kịch câm / wasm hoặc nếu không, hãy sử dụng WebAssembly.instantiate (arraybuffer, importObject).
Hỗ trợ WebAssembly được thêm vào tất cả các trình duyệt mới nhất hiện có với bạn như Chrome, Firefox. Phiên bản Firefox 54+ trở đi cung cấp cho bạn một tính năng đặc biệt để gỡ lỗi mã wasm của bạn.
Để làm điều đó, hãy thực thi mã của bạn bên trong các trình duyệt Firefox gọi là wasm. Ví dụ, hãy xem xét mã C sau đây để tìm bình phương của số.
Một ví dụ cho Chương trình C như sau:
#include<stdio.h>
int square(int n) {
return n*n;
}
Chúng tôi sẽ sử dụng trình thám hiểm WASM để lấy mã wasm -
Tải xuống mã WASM và sử dụng nó để xem kết quả đầu ra trong trình duyệt.
Tệp html tải wasm như sau:
!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>WebAssembly Square function</title>
<style>
div {
font-size : 30px; text-align : center; color:orange;
}
</style>
</head>
<body>
<div id="textcontent"></div>
<script>
let square;
fetch("findsquare.wasm").then(bytes => bytes.arrayBuffer())
.then(mod => WebAssembly.compile(mod))
.then(module => {return new WebAssembly.Instance(module) })
.then(instance => {
square = instance.exports.square(13);
console.log("The square of 13 = " +square);
document.getElementById("textcontent").innerHTML = "The square of 13 = " +square;
});
</script>
</body>
</html>
Mở trình duyệt Firefox của bạn và tải tệp html ở trên và mở công cụ gỡ lỗi.
Bạn sẽ thấy mục nhập wasm: // trong công cụ gỡ lỗi. Nhấp vào wasm: // và nó hiển thị mã wasm được chuyển đổi sang định dạng .wat như hình trên.
Bạn có thể xem mã của hàm đã xuất và có thể gỡ lỗi mã, nếu có bất kỳ vấn đề nào xảy ra. Firefox cũng có ý định thêm các điểm ngắt, để bạn có thể gỡ lỗi mã và kiểm tra quy trình thực thi.
Trong chương này, chúng ta sẽ viết một chương trình đơn giản bằng C và chuyển đổi nó thành .wasm và thực thi tương tự trong trình duyệt để nhận được văn bản "Hello World".
Sẽ sử dụng công cụ wasm explorer sẽ chuyển đổi chương trình C thành .wasm và sẽ sử dụng .wasm bên trong tệp .html của chúng tôi.
Công cụ khám phá Wasm có sẵn tại https://mbebenita.github.io/WasmExplorer/ looks as follows −
Mã C mà chúng ta sẽ sử dụng như sau:
#include <stdio.h>
char *c_hello() {
return "Hello World";
}
Cập nhật khối đầu tiên trong wasm explorer với mã C như hình dưới đây -
Nhấp vào nút COMPILE để biên dịch sang WASM và WAT và Firefox x86 Web Assembly như hình dưới đây -
Sử dụng TẢI XUỐNG để lấy tệp .wasm và lưu dưới dạng firstprog.wasm.
Tạo một tệp .html có tên firstprog.html như hình dưới đây -
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>WebAssembly Hello World</title>
</head>
<body>
<div id="textcontent"></div>
<script type="text/javascript">
//Your code from webassembly here
</script>
</body>
</html>
Bây giờ chúng ta hãy sử dụng firstprog.wasm để đọc helloworld từ hàm C c_hello ().
Bước 1
Sử dụng api fetch () để đọc mã firstprog.wasm.
Bước 2
Mã .wasm phải được chuyển đổi thành bộ đệm mảng bằng cách sử dụng ArrayBuffer. Đối tượng ArrayBuffer sẽ trả về cho bạn một bộ đệm dữ liệu nhị phân có độ dài cố định.
Mã cho đến nay sẽ như sau:
<script type="text/javascript">
fetch("firstprog.wasm") .then(bytes => bytes.arrayBuffer())
</script>
Bước 3
Các byte từ ArrayBuffer phải được biên dịch thành một mô-đun bằng cách sử dụng WebAssembly.compile(buffer) chức năng.
Mã sẽ giống như dưới đây:
<script type="text/javascript">
fetch("firstprog.wasm")
.then(bytes => bytes.arrayBuffer())
.then(mod => WebAssembly.compile(mod))
</script>
Bước 4
Để có được mô-đun, chúng ta phải gọi hàm tạo webassembly.instance như hình dưới đây:
<script type="text/javascript">
fetch("firstprog.wasm")
.then(bytes => bytes.arrayBuffer())
.then(mod => WebAssembly.compile(mod))
.then(module => {return new WebAssembly.Instance(module) })
</script>
Bước 5
Bây giờ chúng ta hãy điều khiển phiên bản để xem chi tiết trong trình duyệt.
<script type="text/javascript">
fetch("firstprog.wasm") .then(bytes => bytes.arrayBuffer())
.then(mod => WebAssembly.compile(mod)) .then(module => {
return new WebAssembly.Instance(module)
})
.then(instance => {
console.log(instance);
});
</script>
Chi tiết console.log được hiển thị bên dưới:
Để lấy chuỗi “Hello World” từ hàm c_hello (), chúng ta cần thêm một số mã trong javascript.
Đầu tiên, lấy chi tiết bộ nhớ đệm như hình dưới đây -
let buffer = instance.exports.memory.buffer;;
Giá trị bộ đệm phải được chuyển đổi thành một mảng đã nhập để chúng ta có thể đọc các giá trị từ nó. Bộ đệm có chuỗi Hello World trong đó.
Để chuyển đổi sang kiểu gõ, hãy gọi hàm tạo Uint8Array như hình dưới đây:
let buffer = new Uint8Array(instance.exports.memory.buffer);
Bây giờ, chúng ta có thể đọc giá trị từ bộ đệm trong một vòng lặp for.
Bây giờ chúng ta hãy lấy điểm bắt đầu để đọc bộ đệm, bằng cách gọi hàm chúng ta đã viết như hình dưới đây:
let test = instance.exports.c_hello();
Bây giờ, biến kiểm tra có điểm bắt đầu để đọc chuỗi của chúng ta. WebAssembly không có bất kỳ thứ gì cho giá trị chuỗi, mọi thứ được lưu trữ dưới dạng số nguyên.
Vì vậy, khi chúng ta đọc giá trị từ bộ đệm, chúng sẽ là một giá trị số nguyên và chúng ta cần chuyển nó thành một chuỗi bằng cách sử dụng fromCharCode () trong javascript.
Mã như sau:
let mytext = "";
for (let i=test; buffer[i]; i++){
mytext += String.fromCharCode(buffer[i]);
}
Bây giờ, khi bạn điều khiển mytext, bạn sẽ thấy chuỗi “Hello World”.
Thí dụ
Mã hoàn chỉnh như sau:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>WebAssembly Add Function</title>
<style>
div {
font-size : 30px; text-align : center; color:orange;
}
</style>
</head>
<body>
<div id="textcontent"></div>
<script>
fetch("firstprog.wasm")
.then(bytes => bytes.arrayBuffer())
.then(mod => WebAssembly.compile(mod))
.then(module => {return new WebAssembly.Instance(module)})
.then(instance => {
console.log(instance);
let buffer = new Uint8Array(instance.exports.memory.buffer);
let test = instance.exports.c_hello();
let mytext = "";
for (let i=test; buffer[i]; i++) {
mytext += String.fromCharCode(buffer[i]);
}
console.log(mytext); document.getElementById("textcontent").innerHTML = mytext;
});
</script>
</body>
</html>
Chúng tôi đã thêm một div và nội dung được thêm vào div, vì vậy chuỗi được hiển thị trên trình duyệt.
Đầu ra
Đầu ra được đề cập bên dưới -
Chúng ta đã biết cách lấy tệp .wasm từ mã c / c ++. Trong chương này, chúng tôi sẽ chuyển đổi wasm thành một mô-đun WebAssembly và thực thi tương tự trong trình duyệt.
Hãy để chúng tôi sử dụng mã Giai thừa C ++ như hình dưới đây:
int fact(int n) {
if ((n==0)||(n==1))
return 1;
else
return n*fact(n-1);
}
Mở Wasm Explorer có sẵn tại https://mbebenita.github.io/WasmExplorer/ as shown below −
Cột đầu tiên có chức năng giai thừa C ++, cột thứ 2 có định dạng văn bản WebAssembly và cột cuối cùng có mã Assembly x86.
Định dạng văn bản của WebAssembly -
(module
(table 0 anyfunc)
(memory $0 1)
(export "memory" (memory $0)) (export "_Z4facti" (func $_Z4facti))
(func $_Z4facti (; 0 ;) (param $0 i32) (result i32)
(local $1 i32) (set_local $1
(i32.const 1)
)
(block $label$0
(br_if $label$0
(i32.eq
(i32.or
(get_local $0) (i32.const 1) ) (i32.const 1) ) ) (set_local $1
(i32.const 1)
)
(loop $label$1
(set_local $1 (i32.mul (get_local $0)
(get_local $1) ) ) (br_if $label$1 (i32.ne (i32.or (tee_local $0
(i32.add
(get_local $0) (i32.const -1) ) ) (i32.const 1) ) (i32.const 1) ) ) ) ) (get_local $1)
)
)
Hàm C ++ fact đã được xuất dưới dạng “_Z4facti”Ở định dạng Văn bản của WebAssembly.
Nhấp vào nút tải xuống để tải xuống mã wasm và lưu tệp dưới dạng factorial.wasm.
Bây giờ để chuyển đổi mã .wasm sang mô-đun, chúng ta phải làm như sau:
Bước 1
Chuyển đổi .wasm thành bộ đệm mảng bằng cách sử dụng ArrayBuffer. Đối tượng ArrayBuffer sẽ trả về cho bạn một bộ đệm dữ liệu nhị phân có độ dài cố định.
Bước 2
Các byte từ ArrayBuffer phải được biên dịch thành một mô-đun bằng cách sử dụng WebAssembly.compile(buffer) chức năng.
Các WebAssembly.compile() hàm biên dịch và trả về một WebAssembly.Module từ các byte đã cho.
Đây là mã Javascript được thảo luận ở Bước 1 và 2.
<script type="text/javascript">
let factorial;
fetch("factorial.wasm")
.then(bytes => bytes.arrayBuffer())
.then(mod => WebAssembly.compile(mod))
.then(module => {return new WebAssembly.Instance(module) })
.then(instance => {
factorial = instance.exports._Z4facti;
console.log('Test the output in Brower Console by using factorial(n)');
});
</script>
Giải thích mã
Tìm nạp API trình duyệt Javascript được sử dụng để lấy nội dung của factorial.wasm.
Nội dung được chuyển đổi thành byte bằng cách sử dụng arrayBuffer ().
Mô-đun được tạo từ các byte bằng cách gọi WebAssembly.compile (mod).
Phiên bản của một mô-đun được tạo bằng cách sử dụng
WebAssembly.Instance(module)
Việc xuất hàm giai thừa _Z4facti được gán cho giai thừa biến bằng cách sử dụng WebAssembly.Module.exports ().
Thí dụ
Đây là module.html cùng với mã javascript -
module.html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>WebAssembly Module</title>
</head>
<body>
<script>
let factorial;
fetch("factorial.wasm")
.then(bytes => bytes.arrayBuffer())
.then(mod => WebAssembly.compile(mod))
.then(module => {return new WebAssembly.Instance(module) })
.then(instance => {
factorial = instance.exports._Z4facti;
console.log('Test the output in Browser Console by using factorial(n)');
});
</script>
</body>
</html>
Đầu ra
Thực thi module.html trong trình duyệt để xem kết quả -
Trong chương này, chúng ta sẽ thảo luận về hàm webassembly.validate () sẽ xác thực đầu ra .wasm. .Wasm có sẵn khi chúng ta biên dịch C, C ++ hoặc mã gỉ.
Bạn có thể sử dụng các công cụ sau để lấy mã wasm.
Wasm Fiddler, có sẵn tại https://wasdk.github.io/WasmFiddle/
WebAssembly Explorer, có sẵn tại https://mbebenita.github.io/WasmExplorer/.
Cú pháp
Cú pháp như dưới đây:
WebAssembly.validate(bufferSource);
Thông số
bufferSource- BufferSource có mã nhị phân đến từ chương trình C, C ++ hoặc Rust. Nó ở dạng typedarray hoặc ArrayBuffer.
Giá trị trả lại
Hàm sẽ trả về true nếu mã .wasm hợp lệ và false nếu không.
Hãy để chúng tôi thử một ví dụ. Đi đến Wasm fiddler , có sẵn tạihttps://wasdk.github.io/WasmFiddle/, nhập mã C mà bạn chọn và nhập mã wasm.
Khối được đánh dấu màu đỏ là mã C. Nhấp vào nút Build ở giữa để thực thi mã.
Nhấp vào nút Wasm, để tải xuống mã .wasm. Lưu .wasm vào cuối của bạn và cho phép chúng tôi sử dụng nó để xác thực.
Thí dụ
Ví dụ: validate.html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Testing WASM validate()</title>
</head>
<body>
<script>
fetch('program.wasm').then(res => res.arrayBuffer() ).then(function(testbytes) {
var valid = WebAssembly.validate(testbytes);
if (valid) {
console.log("Valid Wasm Bytes!");
} else {
console.log("Invalid Wasm Code!");
}
});
</script>
</body>
</html>
Tôi đã lưu trữ tệp .html ở trên trong máy chủ wamp cùng với tệp .wasm tải xuống. Đây là kết quả đầu ra khi bạn kiểm tra nó trên trình duyệt.
Đầu ra
Đầu ra được đề cập bên dưới -
WebAssembly có mã ở định dạng nhị phân gọi là WASM. Bạn cũng có thể lấy định dạng văn bản trong WebAssembly và nó được gọi là WAT (WebAssembly văn bản định dạng). Là một nhà phát triển, bạn không được phép viết mã trong WebAssembly, thay vào đó, bạn phải biên dịch các ngôn ngữ cấp cao như C, C ++ và Rust sang WebAssembly.
Mã WAT
Hãy để chúng tôi viết mã WAT theo từng bước.
Step 1 - Điểm bắt đầu trong một WAT là khai báo mô-đun.
(module)
Step 2 - Bây giờ chúng ta hãy thêm một số chức năng vào nó dưới dạng hàm.
Hàm được khai báo như hình dưới đây:
(func <parameters/result> <local variables> <function body>)
Hàm bắt đầu bằng từ khóa func, theo sau là các tham số hoặc kết quả.
Tham số / Kết quả
Các tham số và giá trị trả về là kết quả.
Các tham số có thể có kiểu sau được hỗ trợ bởi wasm:
- i32: số nguyên 32 bit
- i64: số nguyên 64 bit
- f32: 32-bit float
- f64: 64-bit float
Các tham số cho các hàm được viết như dưới đây:
- (param i32)
- (tham số i64)
- (thông số f32)
- (thông số f64)
Kết quả sẽ được viết như sau:
- (kết quả i32)
- (kết quả i64)
- (kết quả f32)
- (kết quả f64)
Hàm với các tham số và giá trị trả về sẽ được định nghĩa như sau:
(func (param i32) (param i32) (result i64) <function body>)
Biến cục bộ
Các biến cục bộ là những biến bạn cần trong hàm của mình. Giá trị cục bộ của hàm sẽ được định nghĩa như sau:
(func (param i32) (param i32) (local i32) (result i64) <function body>)
Cơ quan chức năng
Phần thân hàm là logic được thực hiện. Chương trình cuối cùng sẽ như thế này -
(module (func (param i32) (param i32) (local i32) (result i64) <function body>) )
Step 3 - Để đọc và thiết lập các tham số và biến cục bộ.
Để đọc các tham số và biến cục bộ, hãy sử dụng get_local và set_local chỉ huy.
Example
(module
(func (param i32) (param i32) (local i32) (result i64) get_local 0
get_local 1
get_local 2
)
)
Theo chữ ký hàm,
get_local 0 sẽ cung cấp cho param i32
get_local 1 sẽ đưa ra thông số tiếp theo param i32
get_local 2 sẽ cho local value i32
Thay vì đề cập đến các tham số và địa phương bằng cách sử dụng các giá trị số như 0,1,2, bạn cũng có thể sử dụng tên trước các tham số, đặt trước tên bằng một ký hiệu đô la.
Ví dụ sau đây cho thấy, cách sử dụng tên với các tham số và địa phương.
Example
(module
(func
(param $a i32) (param $b i32)
(local $c i32) (result i64) get_local $a get_local $b get_local $c
)
)
Step 4 - Lệnh trong phần thân Chức năng và thực thi.
Việc thực thi trong wasm tuân theo chiến lược ngăn xếp. Các lệnh được thực thi được gửi lần lượt trên ngăn xếp. Ví dụ, lệnh get_local $ a sẽ đẩy giá trị, nó đọc trên ngăn xếp.
Hướng dẫn như i32.add điều đó sẽ thêm ý chí bật các phần tử từ ngăn xếp.
(func (param $a i32) (param $b i32) get_local $a
get_local $b
i32.add
)
Hướng dẫn cho i32.add Là ($a+$b). Giá trị cuối cùng của i32.add, sẽ được đẩy lên ngăn xếp và giá trị đó sẽ được gán cho kết quả.
Nếu chữ ký hàm có một kết quả được khai báo, thì phải có một giá trị trong ngăn xếp ở cuối quá trình thực thi. Nếu không có tham số kết quả, ngăn xếp phải trống ở cuối.
Vì vậy, mã cuối cùng cùng với phần thân hàm sẽ như sau:
(module
(func (param $a i32) (param $b i32) (result i32) get_local $a
get_local $b
i32.add
)
)
Step 5 - Thực hiện cuộc gọi đến chức năng.
Đoạn mã cuối cùng với phần thân hàm như được hiển thị trong bước 4. Bây giờ, để gọi hàm, chúng ta cần xuất nó.
Để xuất hàm, nó có thể được thực hiện với các giá trị chỉ mục như 0,1, nhưng, chúng ta cũng có thể đặt tên. Tên sẽ có tiền tố là $ và nó sẽ được thêm vào sau từ khóa func.
Example
(module
(func $add (param $a i32) (param $b i32) (result i32) get_local $a
get_local $b i32.add
)
)
Hàm $ add phải được xuất, sử dụng từ khóa export như hình dưới đây -
(module
(func $add (param $a i32)
(param $b i32) (result i32) get_local $a get_local $b i32.add ) (export "add" (func $add))
)
Để kiểm tra đoạn mã trên trong trình duyệt, bạn sẽ phải chuyển nó thành dạng nhị phân (.wasm). Tham khảo chương tiếp theo hướng dẫn cách chuyển đổi.WAT to .WASM.
Trong chương trước, chúng ta đã biết cách viết mã trong .wattức là, định dạng văn bản WebAssembly. Định dạng văn bản WebAssembly sẽ không trực tiếp hoạt động bên trong trình duyệt và bạn cần chuyển đổi nó thành định dạng nhị phân, tức là WASM để hoạt động bên trong trình duyệt.
WAT thành WASM
Hãy để chúng tôi chuyển đổi .WAT thành .WASM.
Mã chúng tôi sẽ sử dụng như sau:
(module
(func $add (param $a i32) (param $b i32) (result i32) get_local $a
get_local $b i32.add ) (export "add" (func $add))
)
Bây giờ, đi tới WebAssembly Studio, có sẵn tại https://webassembly.studio/.
Bạn sẽ thấy một cái gì đó như thế này, khi bạn nhấn vào liên kết -
Nhấp vào dự án Empty Wat và nhấp vào nút Tạo ở dưới cùng.
Nó sẽ đưa bạn đến một dự án trống như hình dưới đây -
Nhấp vào main.wat và thay thế mã hiện có bằng mã của bạn và nhấp vào nút lưu.
Sau khi lưu, hãy nhấp vào bản dựng để chuyển đổi thành .wasm -
Nếu quá trình xây dựng thành công, bạn sẽ thấy tệp .wasm được tạo như hình dưới đây:
Xuống tệp main.wasm và sử dụng nó bên trong tệp .html của bạn để xem kết quả như hình dưới đây.
Ví dụ - add.html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>WebAssembly Add Function</title>
</head>
<body>
<script>
let sum;
fetch("main.wasm")
.then(bytes => bytes.arrayBuffer())
.then(mod => WebAssembly.compile(mod)) .then(module => {
return new WebAssembly.Instance(module)
})
.then(instance => {
sum = instance.exports.add(10,40);
console.log("The sum of 10 and 40 = " +sum);
});
</script>
</body>
</html>
Hàm thêm được xuất như trong mã. Các tham số được truyền là 2 giá trị nguyên 10 và 40 và nó trả về tổng của nó.
Đầu ra
Kết quả được hiển thị trong trình duyệt.
Liên kết động là quá trình trong đó hai hoặc nhiều mô-đun sẽ được liên kết với nhau trong thời gian chạy.
Để chứng minh cách hoạt động của liên kết động, chúng tôi sẽ sử dụng chương trình C và biên dịch nó thành wasm bằng cách sử dụng Ecmascript sdk.
Vì vậy, ở đây chúng tôi có -
test1.c
int test1(){
return 100;
}
test2.c
int test2(){
return 200;
}
main.c
#include <stdio.h>
int test1();
int test2();
int main() {
int result = test1() + test2();
return result;
}
Trong mã main.c, nó sử dụng test1 () và test2 (), được định nghĩa bên trong test1.c và test2.c. Hãy để chúng tôi kiểm tra cách liên kết các mô-đun này trong WebAssembly.
Lệnh để biên dịch đoạn mã trên như sau: sử dụng SIDE_MODULE = 1 cho liên kết động như được hiển thị trong lệnh.
emcc test1.c test2.c main.c -s SIDE_MODULE=1 -o maintest.wasm
Sử dụng WasmtoWat, có sẵn tại https://webassembly.github.io/wabt/demo/wasm2wat/, sẽ nhận được định dạng văn bản WebAssembly của Maintest.wasm.
(module
(type $t0 (func (result i32))) (type $t1 (func))
(type $t2 (func (param i32))) (type $t3 (func (param i32 i32) (result i32)))
(import "env" "stackSave" (func $env.stackSave (type $t0)))
(import "env" "stackRestore" (func $env.stackRestore (type $t2)))
(import "env" "__memory_base" (global $env.__memory_base i32)) (import "env" "__table_base" (global $env.__table_base i32))
(import "env" "memory" (memory $env.memory 0)) (import "env" "table" (table $env.table 0 funcref))
(func $f2 (type $t1)
(call $__wasm_apply_relocs) ) (func $__wasm_apply_relocs (export "__wasm_apply_relocs") (type $t1)) (func $test1 (export "test1") (type $t0) (result i32) (local $l0 i32)
(local.set $l0 (i32.const 100) ) (return (local.get $l0)
)
)
(func $test2 (export "test2") (type $t0) (result i32)
(local $l0 i32) (local.set $l0
(i32.const 200))
(return
(local.get $l0) ) ) (func $__original_main
(export "__original_main")
(type $t0) (result i32) (local $l0 i32)
(local $l1 i32) (local $l2 i32)
(local $l3 i32) (local $l4 i32)
(local $l5 i32) (local $l6 i32)
(local $l7 i32) (local $l8 i32)
(local $l9 i32) (local.set $l0(call $env.stackSave)) (local.set $l1 (i32.const 16))
(local.set $l2 (i32.sub (local.get $l0) (local.get $l1))) (call $env.stackRestore (local.get $l2) ) (local.set $l3(i32.const 0))
(i32.store offset=12 (local.get $l2) (local.get $l3))
(local.set $l4 (call $test1))
(local.set $l5 (call $test2))
(local.set $l6 (i32.add (local.get $l4) (local.get $l5))) (i32.store offset=8 (local.get $l2) (local.get $l6)) (local.set $l7 (i32.load offset=8 (local.get $l2))) (local.set $l8 (i32.const 16))
(local.set $l9 (i32.add (local.get $l2) (local.get $l8))) (call $env.stackRestore (local.get $l9)) (return(local.get $l7))
)
(func $main (export "main") (type $t3)
(param $p0 i32) (param $p1 i32)
(result i32)
(local $l2 i32) (local.set $l2
(call $__original_main)) (return (local.get $l2))
)
(func $__post_instantiate (export "__post_instantiate") (type $t1) (call $f2)) (global $__dso_handle (export "__dso_handle") i32 (i32.const 0))
)
Định dạng văn bản WebAssembly có một số nhập được xác định như hình dưới đây -
(import "env" "stackSave" (func $env.stackSave (type $t0)))
(import "env" "stackRestore" (func $env.stackRestore (type $t2)))
(import "env" "__memory_base" (global $env.__memory_base i32)) (import "env" "__table_base" (global $env.__table_base i32))
(import "env" "memory" (memory $env.memory 0)) (import "env" "table" (table $env.table 0 funcref))
Điều này được thêm vào trong khi biên dịch mã bằng emcc (emscripten sdk) và nó liên quan đến quản lý bộ nhớ trong WebAssembly.
Làm việc với Nhập khẩu và Xuất khẩu
Bây giờ để xem đầu ra, chúng ta sẽ phải xác định các nhập mà bạn có thể thấy trong mã .wat -
(import "env" "stackSave" (func $env.stackSave (type $t0)))
(import "env" "stackRestore" (func $env.stackRestore (type $t2)))
(import "env" "__memory_base" (global $env.__memory_base i32)) (import "env" "__table_base" (global $env.__table_base i32))
(import "env" "memory" (memory $env.memory 0)) (import "env" "table" (table $env.table 0 funcref))
Các thuật ngữ trên được giải thích như sau:
env.stackSave - Nó được sử dụng để quản lý ngăn xếp, một chức năng được cung cấp bởi mã biên dịch emscripten.
env.stackRestore - Nó được sử dụng để quản lý ngăn xếp, một chức năng được cung cấp bởi mã biên dịch emscripten.
env.__memory_base- Nó là một phần bù toàn cục i32 bất biến, được sử dụng trong env.memory và được dành riêng cho mô-đun wasm. Mô-đun có thể sử dụng toàn cục này trong trình khởi tạo các phân đoạn dữ liệu của nó, để chúng được tải ở địa chỉ chính xác.
env.__table_base- Nó là một phần bù toàn cục i32 không thay đổi được, được sử dụng trong env.table và dành riêng cho mô-đun wasm. Mô-đun có thể sử dụng toàn cục này trong trình khởi tạo của các phân đoạn phần tử bảng của nó, do đó, chúng được tải ở độ lệch chính xác.
env.memory - Điều này sẽ có các chi tiết bộ nhớ được yêu cầu chia sẻ giữa các mô-đun wasm.
env.table - Điều này sẽ có các chi tiết bảng được yêu cầu chia sẻ giữa các mô-đun wasm.
Nhập phải được định nghĩa trong javascript như sau:
var wasmMemory = new WebAssembly.Memory({'initial': 256,'maximum': 65536});
const importObj = {
env: {
stackSave: n => 2, stackRestore: n => 3, //abortStackOverflow: () => {
throw new Error('overflow');
},
table: new WebAssembly.Table({
initial: 0, maximum: 65536, element: 'anyfunc'
}), __table_base: 0,
memory: wasmMemory, __memory_base: 256
}
};
Thí dụ
Sau đây là mã javascript sử dụng importObj bên trong WebAssembly.instantiate.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<script>
var wasmMemory = new WebAssembly.Memory({'initial': 256,'maximum': 65536});
const importObj = {
env: {
stackSave: n => 2, stackRestore: n => 3, //abortStackOverflow: () => {
throw new Error('overflow');
},
table: new WebAssembly.Table({
initial: 0, maximum: 65536, element: 'anyfunc'
}), __table_base: 0,
memory: wasmMemory, __memory_base: 256
}
};
fetch("maintest.wasm") .then(bytes => bytes.arrayBuffer()) .then(
module => WebAssembly.instantiate(module, importObj)
)
.then(finalcode => {
console.log(finalcode);
console.log(WebAssembly.Module.imports(finalcode.module));
console.log(finalcode.instance.exports.test1());
console.log(finalcode.instance.exports.test2());
console.log(finalcode.instance.exports.main());
});
</script>
</body>
</html>
Đầu ra
Kết quả như sau:
Theo trang web chính thức của WebAssembly.org, có sẵn tại https://webassembly.org/docs/security/ mục tiêu chính của WebAssembly về mặt bảo mật như sau:
Mô hình bảo mật của WebAssembly có hai mục tiêu quan trọng:
Bảo vệ người dùng khỏi các mô-đun lỗi hoặc độc hại, và
Cung cấp cho các nhà phát triển các nguyên tắc và giảm thiểu hữu ích để phát triển các ứng dụng an toàn, trong các ràng buộc của (1).
Mã đã biên dịch tức là WASM từ C / C ++ / Rust không được thực thi trực tiếp bên trong trình duyệt và sử dụng API của Javascript. Mã WASM được hộp cát tức là được thực thi thông qua trình bao bọc API Javascript và trình duyệt nói chuyện với WASM bằng cách sử dụng API.
Đây là một ví dụ về việc sử dụng tệp .wasm bên trong trình duyệt.
Ví dụ - C Program
#include<stdio.h>
int square(int n) {
return n*n;
}
Chúng tôi sẽ sử dụng trình thám hiểm WASM để lấy mã wasm -
Tải xuống mã WASM và sử dụng nó để kiểm tra api.
Thí dụ
<script type="text/javascript">
const importObj = {
module: {}
};
fetch("findsquare.wasm")
.then(bytes => bytes.arrayBuffer())
.then(module => WebAssembly.instantiate(module,importObj))
.then(finalcode => {
console.log(finalcode); console.log(finalcode.instance.exports.square(25));
});
</script>
Đầu ra
Bạn sẽ nhận được kết quả sau:
Các đối tượng xuất có tham chiếu đến hàm được gọi. Để gọi hàm bình phương, bạn sẽ phải làm như sau:
console.log(finalcode.instance.exports.square(25));
Vấn đề với mã biên dịch WASM
Sau đây là các vấn đề với mã biên dịch WASM -
Rất khó để kiểm tra, nếu có bất kỳ mã độc hại nào được chèn vào, trong khi biên dịch mã thành wasm. Không có công cụ nào có sẵn tại thời điểm này để xác thực mã.
Wasm rất khó phân tích và mã lỗi / mã độc có thể dễ dàng thực thi bên trong trình duyệt.
Trong chương này, chúng ta sẽ biên dịch một chương trình C đơn giản sang javascript và thực thi tương tự trong trình duyệt.
Ví dụ - C Program
#include<stdio.h>
int square(int n) {
return n*n;
}
Chúng tôi đã thực hiện cài đặt emsdk trong thư mục wa /. Trong cùng một thư mục, tạo một thư mục khác cprog / và lưu đoạn mã trên dưới dạng square.c.
Chúng tôi đã cài đặt emsdk trong chương trước. Ở đây, chúng ta sẽ sử dụng emsdk để biên dịch mã c ở trên.
Biên dịch test.c trong dấu nhắc lệnh của bạn như hình dưới đây:
emcc square.c -s STANDALONE_WASM –o findsquare.wasm
lệnh emcc đảm nhận việc biên dịch mã cũng như cung cấp cho bạn mã .wasm. Chúng tôi đã sử dụng tùy chọn STANDALONE_WASM sẽ chỉ cung cấp tệp .wasm.
Ví dụ - findsquare.html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>WebAssembly Square function</title>
<style>
div {
font-size : 30px; text-align : center; color:orange;
}
</style>
</head>
<body>
<div id="textcontent"></div>
<script>
let square; fetch("findsquare.wasm").then(bytes => bytes.arrayBuffer())
.then(mod => WebAssembly.compile(mod)) .then(module => {
return new WebAssembly.Instance(module)
})
.then(instance => {
square = instance.exports.square(13);
console.log("The square of 13 = " +square);
document.getElementById("textcontent").innerHTML = "The square of 13 = " +square;
});
</script>
</body>
</html>
Đầu ra
Đầu ra như được đề cập bên dưới -
Trong chương này, chúng ta sẽ biên dịch một chương trình C ++ đơn giản sang javascript và thực thi tương tự trong trình duyệt.
Thí dụ
Chương trình C ++ - Đảo ngược một số nhất định.
#include <iostream>
int reversenumber(int n) {
int reverse=0, rem;
while(n!=0) {
rem=n%10; reverse=reverse*10+rem; n/=10;
}
return reverse;
}
Chúng tôi đã thực hiện cài đặt emsdk trong thư mục wa /. Trong cùng một thư mục, tạo một thư mục khác cprog / và lưu đoạn mã trên dưới dạng reverse.cpp.
Chúng tôi đã cài đặt emsdk trong chương trước. Ở đây, chúng ta sẽ sử dụng emsdk để biên dịch mã c ở trên.
Biên dịch test.c trong dấu nhắc lệnh của bạn như hình dưới đây:
emcc reverse.cpp -s STANDALONE_WASM –o reverse.wasm
lệnh emcc đảm nhận việc biên dịch mã cũng như cung cấp cho bạn mã .wasm.
Ví dụ - reversenumber.html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>WebAssembly Reverse Number</title>
<style>
div {
font-size : 30px; text-align : center; color:orange;
}
</style>
</head>
<body>
<div id="textcontent"></div>
<script>
let reverse;
fetch("reverse.wasm")
.then(bytes => bytes.arrayBuffer())
.then(mod => WebAssembly.compile(mod))
.then(module => {return new WebAssembly.Instance(module) })
.then(instance => {
console.log(instance);
reverse = instance.exports._Z13reversenumberi(1439898);
console.log("The reverse of 1439898 = " +reverse);
document.getElementById("textcontent")
.innerHTML = "The reverse of 1439898 = " +reverse;
});
</script>
</body>
</html>
Đầu ra
Kết quả như sau:
Để có được mã biên dịch RUST, chúng tôi sẽ sử dụng công cụ WebAssembly.studio.
Đến WebAssembly.studio trong đó có sẵn tại Đếnhttps://webassembly.studio/ và nó sẽ hiển thị cho bạn màn hình như hình dưới đây -
Nhấn vào Empty Rust Project. Sau khi hoàn tất, bạn sẽ nhận được ba tệp trong thư mục src / -
Mở tệp main.rs và thay đổi mã bạn chọn.
Tôi đang thêm hàm sau sẽ thêm hai số nhất định:
fn add_ints(lhs: i32, rhs: i32) -> i32 {
lhs+rhs
}
Mã có sẵn trong main.rs như sau:
#[no_mangle]
pub extern "C" fn add_one(x: i32) -> i32 {
x + 1
}
Thay thế add_one fn bằng của bạn như hình dưới đây -
#[no_mangle]
pub extern "C" fn add_ints(lhs: i32, rhs: i32) -> i32 {
lhs+rhs
}
Trong main.js, thay đổi tên hàm từ add_one thành add_ints
fetch('../out/main.wasm').then(
response =>
response.arrayBuffer()
).then(bytes => WebAssembly.instantiate(bytes)).then(results => {
instance = results.instance;
document.getElementById("container").textContent = instance.exports.add_one(41);
}).catch(console.error);
Thay thế instance.exports.add_one thành instance.exports.add_ints (100,100)
fetch('../out/main.wasm').then(
response =>
response.arrayBuffer()
).then(bytes => WebAssembly.instantiate(bytes)).then(results => {
instance = results.instance;
document.getElementById("container").textContent = instance.exports.add_ints(100,100)
}).catch(console.error);
Nhấp vào nút xây dựng có sẵn trên giao diện người dùng webassembly.studio để xây dựng mã.
Sau khi xây dựng xong, hãy nhấp vào nút Chạy có sẵn trên giao diện người dùng, để xem kết quả -
Chúng tôi nhận được kết quả đầu ra là 200, khi chúng tôi truyền instance.exports.add_ints (100,100).
Tương tự, bạn có thể viết một chương trình khác cho gỉ và biên dịch nó trong webassembly.studio.
Go đã hỗ trợ thêm cho WebAssembly từ phiên bản 1.1 trở đi. Để kiểm tra nó, trước tiên hãy tải xuống.
Truy cập trang web golang, có sẵn tại https://golang.org/dl/và nhấp vào Tải xuống Go. Theo hệ điều hành của bạn, hãy tải xuống và cài đặt Go.
Sau khi hoàn tất, hãy viết một chương trình đơn giản để thêm hai số.
testnum.go
package main
import "fmt"
func main() {
var a int = 100
var b int = 200
var ret int
ret = sum(a, b)
fmt.Printf( "Sum is : %d\n", ret )
}
/* function returning the max between two numbers */
func sum(num1, num2 int) int {
return num1+num2
}
Để biên dịch mã trên thành wasm, trước tiên hãy đặt các biến môi trường trong Go.
Bạn sẽ phải chạy lệnh sau:
Set GOOS=js
GOARCH=wasm
Sau khi hoàn tất, hãy thực hiện lệnh dưới đây:
go build -o testnum.wasm testnum.go
Bạn sẽ nhận được tệp testnum.wasm sau khi lệnh được thực thi.
Bây giờ hãy để chúng tôi kiểm tra mã trong trình duyệt. Để làm điều đó, chúng ta cần lấy wasm_exec.js, được cài đặt sẵn.
Tệp wasm_exec.js sẽ có sẵn trong thư mục misc / wasm / khi di chuyển.
Thí dụ
Đây là mã cho testgo.html sử dụng wasm_exec.js và testnum.wasm.
<html>
<head>
<meta charset="utf-8"/>
<script src="wasm_exec.js"></script>
</head>
<body>
<script type="text/javascript">
const importObj = {
module: {}
};
const go = new Go();
async function fetchAndInstantiate() {
const response = await fetch("testnum.wasm");
const buffer = await response.arrayBuffer();
const obj = await WebAssembly.instantiate(buffer, go.importObject);
console.log(obj);
go.run(obj.instance);
}
fetchAndInstantiate();
</script>
</body>
</html>
Đầu ra
Kết quả như sau:
Javascript có một loạt API có thể hoạt động với mã wasm. API cũng được hỗ trợ trong nodejs.
Cài đặt NODEJS trên hệ thống của bạn. Tạo tệp Factorialtest.js.
Hãy để chúng tôi sử dụng mã Giai thừa C ++ như hình dưới đây:
int fact(int n) {
if ((n==0)||(n==1))
return 1;
else
return n*fact(n-1);
}
Mở Wasm Explorer, có sẵn tại https://mbebenita.github.io/WasmExplorer/ như hình dưới đây -
Cột đầu tiên có chức năng giai thừa C ++, cột thứ 2 có định dạng văn bản WebAssembly và cột cuối cùng có mã Assembly x86.
Định dạng Văn bản của WebAssembly như sau:
(module
(table 0 anyfunc)
(memory $0 1) (export "memory" (memory $0))
(export "_Z4facti" (func $_Z4facti)) (func $_Z4facti (; 0 ;) (param $0 i32) (result i32) (local $1 i32)
(set_local $1(i32.const 1)) (block $label$0 (br_if $label$0 (i32.eq (i32.or (get_local $0)
(i32.const 1)
)
(i32.const 1)
)
)
(set_local $1 (i32.const 1) ) (loop $label$1 (set_local $1
(i32.mul
(get_local $0) (get_local $1)
)
)
(br_if $label$1
(i32.ne
(i32.or
(tee_local $0 (i32.add (get_local $0)
(i32.const -1)
)
)
(i32.const 1)
)
(i32.const 1)
)
)
)
)
(get_local $1)
)
)
Thực tế hàm C ++ đã được xuất dưới dạng “_Z4facti”Ở định dạng Văn bản của WebAssembly.
Factorialtest.js
const fs = require('fs');
const buf = fs.readFileSync('./factorial.wasm');
const lib = WebAssembly.instantiate(new Uint8Array(buf)).
then(res => {
for (var i=1;i<=10;i++) {
console.log("The factorial of "+i+" = "+res.instance.exports._Z4facti(i))
}
}
);
Trong dòng lệnh của bạn, hãy chạy nút lệnh factorialtest.js và kết quả như sau:
C:\wasmnode>node factorialtest.js
The factorial of 1 = 1
The factorial of 2 = 2
The factorial of 3 = 6
The factorial of 4 = 24
The factorial of 5 = 120
The factorial of 6 = 720
The factorial of 7 = 5040
The factorial of 8 = 40320
The factorial of 9 = 362880
The factorial of 10 = 3628800
Chương này thảo luận về các ví dụ liên quan đến WebAssembly.
ví dụ 1
Sau đây là ví dụ về Chương trình C để lấy Phần tử tối đa -
void displaylog(int n);
/* function returning the max between two numbers */
int max(int num1, int num2) {
/* local variable declaration */ int result;
if (num1 > num2)
result = num1;
else result = num2;
displaylog(result);
return result;
}
Biên dịch mã trong wasm fiddle và tải xuống mã .wasm và .wat.
Wat code
Mã Wat như sau:
(module
(type $FUNCSIG$vi (func (param i32))) (import "env" "displaylog" (func $displaylog (param i32)))
(table 0 anyfunc)
(memory $0 1) (export "memory" (memory $0))
(export "max" (func $max)) (func $max (; 1 ;) (param $0 i32) (param $1 i32) (result i32)
(call $displaylog (tee_local $0
(select
(get_local $0) (get_local $1)
(i32.gt_s (get_local $0) (get_local $1))
)
)
)
(get_local $0)
)
)
Tải xuống mã .wasm và cho chúng tôi sử dụng trong tệp .html như hình dưới đây -
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<script>
const importObj = {
env: {
displaylog: n => alert("The max of (400, 130) is " +n)
}
};
fetch("testmax.wasm") .then(bytes => bytes.arrayBuffer())
.then(module => WebAssembly.instantiate(module, importObj))
.then(finalcode => {
console.log(finalcode);
console.log(finalcode.instance.exports.max(400,130));
});
</script>
</body>
</html>
Đầu ra
Kết quả như sau:
Ví dụ 2
Sau đây là mã C ++ để lấy chuỗi fibonacci của số đã cho.
#include <iostream>>
void displaylog(int n);
int fibonacciSeries(int number) {
int n1=0,n2=1,n3,i;
for(i=2;i<number;++i) {
n3=n1+n2; displaylog(n); n1=n2; n2=n3;
}
return 0;
}
Tôi đang sử dụng wasm explorer để biên dịch mã. Tải xuống Wat và Wasm và kiểm tra tương tự trên trình duyệt.
Bạn có thể sử dụng mã được đề cập bên dưới -
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<script>
const importObj = {
env: { _Z10displaylogi: n => console.log(n) }
};
fetch("fib.wasm")
.then(bytes => bytes.arrayBuffer())
.then(module => WebAssembly.instantiate(module, importObj))
.then(finalcode => {
console.log(finalcode);
console.log(finalcode.instance.exports._Z15fibonacciSeriesi(10));
});
</script>
</body>
</html>
Đầu ra
Kết quả như sau:
Ví dụ 3
Sau đây là mã Rust để thêm các phần tử trong một mảng nhất định.
fn add_array(x: i32) -> i32 {
let mut sum = 0;
let mut numbers = [10,20,30]; for i in 0..3 {
sum += numbers[i];
}
sum
}
Chúng tôi sẽ sử dụng WebAssembly Studio để biên dịch RUST thành wasm.
Xây dựng mã và tải xuống tệp wasm và thực thi tương tự trong trình duyệt.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<script>
const importObj = {
env: {
}
};
fetch("add_array.wasm") .then(bytes => bytes.arrayBuffer())
.then(module => WebAssembly.instantiate(module, importObj))
.then(finalcode => {
console.log(finalcode);
console.log(finalcode.instance.exports.add_array());
});
</script>
</body>
</html>
Đầu ra
Đầu ra sẽ như dưới đây: