| 作者 |
| 丁尔男 柴树杉 张秀宏 |
| 丛书名 |
| 出版社 |
| 机械工业出版社 |
| ISBN |
| 9782012111500 |
| 简要 |
| 简介 |
| 内容简介书籍计算机书籍 ---------------------------面向WebAssembly编程:应用开发方法与实践--------------------------- 内容简介 这是一部讲解如何用高级编程语言开发WebAssembly应用的著作,由国内WebAssembly领域的先驱者和布道者撰写。 全书一共10章,分为三个部分。 第一部分 基础篇(第1~3章) 首先介绍了WebAssembly的基础和工具链Emscripten的用法,然后详细讲解了使用 C/C++语言和Emscripten开发WebAssembly模块的方法。 第二部分 方法篇(第4~8章) 对 Emscripten 运行时、WebAssembly 友好的一般性方法、网络 I/O、并发执行、GUI 及交互等知识点展开了深入的讨论。 第三部分 前沿篇(第9~10章) 详细讲解了WASI以及如何使用 Rust 语言开发 WebAssembly模块和 WASI 应用。 ---------------------------WebAssembly原理与核心技术--------------------------- . 内容简介 WebAssembly是栈式虚拟机和字节码技术的最新应用,在Web开发、后端开发、区块链等领域大显身手,越来越受欢迎。 本书是WebAssembly入门和进阶的必读书,它不仅对WebAssembly的工作原理、核心技术和规范进行了全面的剖析和解读,而且给出了实现WebAssembly解释器和AOT编译器的思路和代码。 本书共14章,分为四个部分: 第一部分 WebAssembly概述(第1章) 主要介绍了WebAssembly的概念、发展历史以及阅读本书需要做的准备工作。 第二部分 二进制和文本格式(第2~4章) 详细讲解了WebAssembly的二进制格式、文本格式以及指令集。 第三部分 虚拟机和解释器(第5~11章) 详细讲解了WebAssembly的解释器和虚拟机的工作原理以及实现思路,包括操作数栈、内存、函数调用、控制指令、链接和实例化、错误处理和验证等。 第四部分 WebAssembly进阶(第12~14章) 深入地讲解了AOT编译器的实现思路和WebAssembly的提案等内容。 通过阅读本书,读者不仅可以理解WebAssembly核心原理,还可以学习如何实现WebAssembly解释器和AOT编译器。即收获了“鱼”,又学会了“渔”。 |
| 目录 |
---------------------------面向WebAssembly编程:应用开发方法与实践--------------------------- 前言 第一篇 基础篇 第1章 认识WebAssembly2 1.1 WebAssembly的诞生背景2 1.2 Web的第4种语言3 1.3 本章小结4 第2章 Emscripten快速入门5 2.1 安装Emscripten5 2.1.1 使用emsdk命令行工具安装Emscripten5 2.1.2 在Docker环境中安装Emscripten7 2.1.3 校验安装8 2.2 你好,世界!8 2.2.1 生成.wasm文件8 2.2.2 运行9 2.2.3 使用Emscripten生成测试页面11 2.3 胶水代码初探12 2.3.1 WebAssembly汇编模块载入12 2.3.2 导出函数封装14 2.3.3 异步加载16 2.4 编译目标及编译流程17 2.4.1 编译目标的选择17 2.4.2 编译流程18 2.5 示例:放大镜特效19 2.5.1 模板程序19 2.5.2 静态的放大镜20 2.5.3 动态的放大镜21 2.6 本章小结24 第3章 C与JavaScript互操作25 3.1 JavaScript调用C函数25 3.1.1 定义函数导出宏25 3.1.2 在JavaScript中调用C导出函数27 3.2 JavaScript函数注入C环境30 3.2.1 C函数声明30 3.2.2 JavaScript实现C函数30 3.2.3 闭包限制及解决办法32 3.2.4 JavaScript函数注入C环境的优缺点33 3.3 单向透明的内存模型33 3.3.1 Module.buffer34 3.3.2 Module.HEAPX34 3.3.3 在JavaScript中访问C/C++环境内存35 3.4 JavaScript与C/C++交换数据37 3.4.1 参数及返回值37 3.4.2 通过内存交换数据39 3.4.3 在JavaScript中分配内存42 3.4.4 字符串43 3.5 EM_ASM系列宏44 3.5.1 EM_ASM44 3.5.2 EM_ASM_/EM_ASM_DOUBLE45 3.5.3 EM_ASM_INT_V/EM_ASM_DOUBLE_V46 3.6 emscripten_run_script()系列函数47 3.6.1 emscripten_run_script()47 3.6.2 emscripten_run_script_int()48 3.6.3 emscripten_run_script_string()49 3.7 ccall()/cwrap()50 3.7.1 ccall()51 3.7.2 cwrap()53 3.7.3 ccall()/cwrap()的潜在风险53 3.8 本章小结56 第二篇 方法篇 第4章 Emscripten运行时58 4.1 main()函数与生命周期58 4.2 消息循环61 4.2.1 emscripten_set_main_loop()61 4.2.2 消息循环的暂停、继续及终止63 4.3 文件系统65 4.3.1 Emscripten虚拟文件系统架构66 4.3.2 基于MEMFS的打包文件系统67 4.3.3 NODEFS文件系统71 4.3.4 IDBFS72 4.4 内存管理73 4.4.1 内存容量/栈容量73 4.4.2 可变内存74 4.4.3 内存分配器75 4.5 Module定制75 4.6 示例:人脸检测78 4.6.1 facedetect_cnn()函数78 4.6.2 facedetect_cnn()函数再封装79 4.6.3 读取图像并检测人脸81 4.6.4 基于SDL显示IplImage图像82 4.7 本章小结84 第5章 WebAssembly友好的一般性方法85 5.1 消息循环分离85 5.1.1 emscripten_set_main_loop()的不足85 5.1.2 在JavaScript中创建定时循环86 5.2 内存对齐88 5.2.1 asm.js88 5.2.2 wasm91 5.2.3 避免及检测未对齐的内存操作92 5.3 使用C接口导出C++对象93 5.4 C++对象生命周期管理97 5.4.1 引用计数97 5.4.2 AddRef()/Release()使用规则98 5.4.3 导出AddRef()/Release()100 5.5 使用C接口注入JavaScript对象103 5.5.1 创建JavaScript对象/ID表103 5.5.2 注入JavaScript对象的生命周期管理104 5.6 小心64位整型数107 5.6.1 WebAssembly原生支持int64108 5.6.2 导出函数包含int64108 5.6.3 注入函数包含int64110 5.7 文件系统的缺陷111 5.8 本章小结112 第6章 网络I/O113 6.1 XMLHttpRequest113 6.1.1 XMLHttpRequest对象使用简介113 6.1.2 XMLHttpRequest对象的C接口封装115 6.1.3 扩展回调处理116 6.2 WebSocket119 6.2.1 创建WebSocket测试服务120 6.2.2 在JavaScript中使用WebSocket121 6.2.3 WebSocket对象的C接口封装122 6.3 本章小结126 第7章 并发执行127 7.1 JavaScript中的并发模型127 7.2 在Worker中使用Emscripten129 7.3 pthread线程132 7.3.1 原子操作132 7.3.2 pthread示例134 7.3.3 在浏览器环境运行pthread示例136 7.4 本章小结137 第8章 GUI及交互138 8.1 Canvas138 8.2 鼠标事件141 8.3 键盘事件144 8.4 Life游戏145 8.4.1 Life简介146 8.4.2 设计要求146 8.4.3 Life游戏C代码146 8.4.4 Life游戏网页代码150 8.4.5 运行Life151 8.5 本章小结152 第三篇 前沿篇 第9章 Rust和WebAssembly154 9.1 Rust入门154 9.1.1 安装Rust开发环境154 9.1.2 你好,世界155 9.1.3 Cargo管理工程155 9.1.4 本地文档156 9.2 你好,WebAssembly157 9.2.1 安装WebAssembly开发环境157 9.2.2 打印“你好,WebAssembly”159 9.3 导入和导出函数159 9.3.1 导出main()函数159 9.3.2 导入宿主打印函数161 9.3.3 导出自定义函数162 9.4 打印命令行参数163 9.4.1 打印字符串163 9.4.2 准备导入env_print_str()函数164 9.4.3 向Rust传入字符串165 9.4.4 命令行参数封装168 9.4.5 传入命令行参数170 9.5 no_std171 9.5.1 输出文件的大小171 9.5.2 通过no_std裁剪标准172 9.5.3 库173 9.6 嵌入C代码174 9.6.1 C语言思维174 9.6.2 连接C语言库175 9.6.3 集成C语言源码175 9.6.4 build.rs自动构建178 9.7 本章小结181 第10章 WASI系统接口182 10.1 WASI简介182 10.2 探秘WASI工作原理183 10.2.1 准备工作183 10.2.2 探秘wasm32-wasi底层184 10.2.3 Rust和wasm32-unknown-unknown185 10.2.4 C/C++编译成WASI程序187 10.2.5 汇编程序189 10.3 WebAssembly虚拟机191 10.3.1 准备WebAssembly测试模块191 10.3.2 Node.js环境:基于wasi包191 10.3.3 Node.js环境:手工实现fd_write()函数192 10.3.4 Rust环境:导入wasi包193 10.3.5 Rust环境:手工实现fd_write()函数195 10.4 wapm包管理器196 10.4.1 安装wapm包管理器196 10.4.2 安装并运行cowsay小程序197 10.4.3 创建wapm模块198 10.5 本章小结200 附录 附录A WebAssembly接口202 附录B 机器指令211 ---------------------------WebAssembly原理与核心技术--------------------------- 前言 第一部分 概述 第1章 Wasm介绍 3 1.1 Wasm简史 3 1.2 Wasm简介 6 1.3 准备工作 10 1.4 你好Wasm 11 1.5 本章小结 13 第二部分 二进制和文本格式 第2章 二进制格式 17 2.1 二进制格式介绍 17 2.1.1 Wasm二进制格式总体结构 18 2.1.2 索引空间 21 2.1.3 实体类型 23 2.2 二进制格式分析 25 2.2.0 魔数和版本号 25 2.2.1 类型段 26 2.2.2 导入段 28 2.2.3 函数段 30 2.2.4 表段 30 2.2.5 内存段 31 2.2.6 全局段 32 2.2.7 导出段 33 2.2.8 起始段 34 2.2.9 元素段 35 2.2.10 代码段 35 2.2.11 数据段 37 2.2.12 自定义段 38 2.3 二进制格式解码 39 2.3.1 LEB128介绍 39 2.3.2 解码基本类型 41 2.3.3 解码向量类型 44 2.3.4 处理tag 44 2.3.5 解码代码项和表达式 45 2.3.6 解码整体结构 45 2.3.7 处理错误情况 47 2.4 实现dump命令 48 2.5 本章小结 50 第3章 指令集 51 3.1 指令集介绍 51 3.1.1 操作码 51 3.1.2 助记符 53 3.1.3 立即数 54 3.1.4 操作数 57 3.2 指令分析 58 3.2.1 数值指令 58 3.2.2 变量指令 60 3.2.3 内存指令 61 3.2.4 结构化控制指令 62 3.2.5 跳转指令 64 3.2.6 函数调用指令 65 3.3 指令解码 66 3.4 完善dump命令 69 3.5 本章小结 70 第4章 文本格式 71 4.1 基本结构 71 4.1.1 类型域 72 4.1.2 导入和导出域 73 4.1.3 函数域 75 4.1.4 表域和元素域 75 4.1.5 内存域和数据域 76 4.1.6 全局域 77 4.1.7 起始域 77 4.2 指令 78 4.2.1 普通形式 78 4.2.2 折叠形式 79 4.3 本章小结 81 第三部分 虚拟机和解释器 第5章 操作数栈 85 5.1 操作数栈 85 5.2 虚拟机 87 5.2.1 指令循环 88 5.2.2 指令分派 88 5.3 参数指令 89 5.3.1 drop指令 90 5.3.2 select指令 90 5.4 数值指令 91 5.4.1 常量指令 92 5.4.2 测试指令 92 5.4.3 比较指令 93 5.4.4 一元算术指令 95 5.4.5 二元算术指令 96 5.4.6 类型转换指令 99 5.5 本章效果 103 5.6 本章小结 105 第6章 内存 107 6.1 内存介绍 107 6.2 内存实现 108 6.3 内存指令 109 6.3.1 size和grow指令 110 6.3.2 加载指令 111 6.3.3 存储指令 113 6.4 本章效果 115 6.5 本章小结 117 第7章 函数调用(上) 119 7.1 函数调用介绍 119 7.2 函数调用实现 122 7.2.1 增强操作数栈 123 7.2.2 添加调用栈 124 7.2.3 增强虚拟机 126 7.2.4 call指令 127 7.3 局部变量指令 129 7.3.1 local.get指令 130 7.3.2 local.set指令 130 7.3.3 local.tee指令 131 7.4 全局变量指令 132 7.4.1 global.get指令 132 7.4.2 global.set指令 133 7.5 本章效果 134 7.6 本章小结 135 第8章 控制指令 137 8.1 控制指令介绍 137 8.1.1 跳转标签 138 8.1.2 跳转标签索引 139 8.1.3 块类型 141 8.2 控制指令实现 142 8.2.1 block和loop指令 142 8.2.2 if指令 144 8.2.3 br指令 146 8.2.4 br_if指令 148 8.2.5 br_table指令 149 8.2.6 return指令 150 8.2.7 unreachable和nop指令 151 8.3 本章效果 152 8.4 本章小结 153 第9章 函数调用(下) 155 9.1 本地函数调用 155 9.1.1 本地函数介绍 155 9.1.2 统一两种函数 158 9.1.3 调用本地函数 159 9.1.4 链接本地函数 161 9.1.5 测试本节代码 162 9.2 间接函数调用 163 9.2.1 间接函数调用介绍 163 9.2.2 实现表 165 9.2.3 初始化表 166 9.2.4 call_indirect指令 167 9.2.5 测试本节代码 168 9.3 本章小结 169 第10章 链接和实例化 171 10.1 定义实例接口 171 10.2 实现实例接口 174 10.2.1 函数 174 10.2.2 表 176 10.2.3 全局变量 177 10.2.4 虚拟机 177 10.3 实例化模块 178 10.4 本章效果 180 10.5 本章小结 183 第11章 错误处理和验证 185 11.1 各种错误 186 11.1.1 解码错误 186 11.1.2 结构错误 188 11.1.3 实例化错误 189 11.1.4 运行时错误 190 11.2 验证整体结构 190 11.3 验证函数字节码 192 11.3.1 数据结构 193 11.3.2 操作数栈 194 11.3.3 控制栈 195 11.3.4 验证指令 197 11.4 本章效果 198 11.5 本章小结 199 第四部分 进阶 第12章 编译为Wasm 203 12.1 控制指令 203 12.2 参数指令 207 12.3 变量指令 208 12.4 内存指令 210 12.5 数值指令 213 12.6 本章小结 215 第13章 AOT编译器 217 13.1 AOT介绍 217 13.2 编译模块 219 13.3 编译函数 220 13.3.1 内部函数 221 13.3.2 外部函数 222 13.3.3 导出函数 222 13.3.4 辅助方法 223 13.4 编译指令 224 13.4.1 参数指令 224 13.4.2 变量指令 225 13.4.3 内存指令 226 13.4.4 数值指令 227 13.4.5 结构化控制指令 228 13.4.6 跳转指令 230 13.4.7 函数调用指令 231 13.5 本章效果 233 13.6 本章小结 234 第14章 提案和前景 235 14.1 提案 235 14.1.1 多块内存 237 14.1.2 内存块操作 237 14.1.3 引用类型 239 14.1.4 尾递归调用 241 14.1.5 异常处理 242 14.1.6 多线程支持 244 14.1.7 其他提案 247 14.2 前景 248 附录A Wasm指令表 249 附录B 二进制格式 253 附录C WAT语法 255 |