WebAssembly 入门(废弃)

该文内容基本废弃,直接查看最新发布的 WebAssembly 相关文章。

快速入门

初次体验其神奇之处可以走一遍 mdn 的教学文档

使用 hexdump main.wasm > main.dump 将二进制文件以每个字节显示为 16 进制和相应的 ASCII 字符输出,然后使用编辑器查看

简介

2019 年 12 月 5 日 W3C 宣布 WebAssembly 核心规范成为正式标准,这标志着以后前端不只是三剑客(html/css/js)了,而是多了一个重量级嘉宾:WebAssembly。

简史

通过了解历史知道 wasm 的优点

wasm 起源于 Emscripten 项目,该项目主要就是将 C++编译为 js。是 alon 觉得 js 运行挺快的,所以想将一些 C++游戏项目移植到浏览器上运行而开发的,后由 Mozilla 接手。

转成 js 后,因为其动态性 JIT 很难进一步优化,所以推出了 asm.js

asm.js 优点:仍然是 js,在所有浏览器上都能正常运行,能识别特殊记号的浏览器就可以进行更好的运行时优化。(保留了所有 js 的缺点,浏览器仍需解析执行脚本、JIT 编译等)

function MyAsmModule() {
  "use asm"; // 告诉浏览器这是一个asm.js模块
  function add(x, y) {
    x = x | 0; // x是整数
    y = y | 0; // y也是整数
    return (x + y) | 0; // 返回值也是整数
  }
  return { add: add };
}

在 Mozilla 开发 asm.js 的同时,google 也在试图解决 js 的性能问题,给出的解决方案是 NaCl(Google Native Client)和 PNaCl(Portable NaCl)。通过 NaCl/PNaC1,Chrome 浏览器可以在沙箱环境中直接执行本地代码。

这两拨人凑合,合作开发了基于字节码的语言 WebAssembly。相当于 google 退一步,Mozilla 进一步。既有类型,又更接近机器码的字节码,不仅能缩小文件体积,减少网络传输时间和解析时间,AOT/JIT 编译器实现起来会更轻松,效果也更好

字节码

汇编语言通常与具体的 CPU 指令集相关,而字节码是和和具体的虚拟机指令集相关。特点是操作码由一个字节组成。(跟 cpu 指令集不同的是,如 x86 的操作码可能是一或两个字节。)

WebAssembly

按字面意思理解,WebAssembly 就是 Web 汇编,是为 Web 浏览器定制的汇编语言。

从现代编译器角度看 wasm 代码

0.找到 main.m 文件 1.预处理器,处理 include、import、宏定义 2.编译器编译,编译成 ir 中间代码 3.后端,生成目标代码 4.汇编 5.链接其他动态库静态库 6.编译成适合某个架构的代码

前端 将高级语言生成中间表示(Intermediate Representation,IR)
中断 对 IR 进行分析和各种优化
后端 生成目标代码。把 IR 转化成平台相关的汇编代码,最终由汇编器编译为机器码

llvm

特点

模块

模块是 Wasm 程序编译、传输和加载的单位。Wasm 规范定义了两种模块格式:二进制格式和文本格式。如果和传统汇编语言做类比,那么 Wasm 模块的二进制格式相当于目标文件或可执行文件格式,文本格式则相当于汇编语言。(更容易进行 AOT/JIT 编译,适合作为目标代码,由其他高级语言编译器生成)

  • 二进制格式 .wasm 设计紧凑,所以小
  • 文本格式 .wat 文件 Wasm 文本格式可以简写为 WAT

还有一种内存格式,Wasm 实现(如解释器)通常会把二进制模块解码为内部形式(即内存格式,比如 C/C++/Go 结构体),然后再进行后续处理

wat

指令集

和 Java 虚拟机一样,Wasm 也采用了栈式虚拟机和字节码

验证

Wasm 模块包含了大量类型信息,这样绝大多数问题就可以通过静态分析在代码执行前被发现,只有少数问题需要推迟到运行时进行检查。

从二进制到可以执行

excute

参考书籍:《WebAssembly 原理与核心技术》张秀宏