WebAssembly 入门课
于航
PayPal 高级软件工程师
10751 人已学习
新⼈⾸单¥29
登录后,你可以任选4讲全文学习
课程目录
已完结/共 23 讲
结束语 (1讲)
WebAssembly 入门课
15
15
1.0x
00:00/00:00
登录|注册

04 | WebAssembly 模块的基本组成结构到底有多简单?

你好,我是于航。今天我来和你聊一聊 Wasm 模块的基本组成结构与字节码分析。
在之前的课程中,我们介绍了 Wasm 其实是一种基于“堆栈机模型” 设计的 V-ISA 指令集。在这节课中,我们将深入 Wasm 模块的字节码结构,探究它在二进制层面的基本布局,以及内部各个结构之间的协作方式。
那为什么要探究 Wasm 在二进制层面的基本布局呢?因为在日常的开发实践中,我们通常只是作为应用者,直接将编译好的 Wasm 二进制模块文件,放到工程中使用就完事了,却很少会去关注 Wasm 在二进制层面的具体组成结构。
但其实只有在真正了解 Wasm 模块的二进制组成结构之后,你才能够知道浏览器引擎在处理和使用一个 Wasm 模块时究竟发生了什么。所以今天我们就将深入到这一部分内容中,透过现象看本质,为你揭开 Wasm 模块内部组成的真实面目 —— Section。相信通过这一讲,你能够从另一个角度看到 Wasm 的不同面貌。

Section 概览

从整体上来看,同 ELF 二进制文件类似,Wasm 模块的二进制数据也是以 Section 的形式被安排和存放的。Section 翻译成中文是“段”,但为了保证讲解的严谨性,以及你在理解上的准确性,后文我会直接使用它的英文名词 Section。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

WebAssembly(Wasm)模块的二进制组成结构以Section的形式存放二进制数据,描述了Wasm模块的特征。MVP标准下可用的Section包括Type、Start、Global和Custom。Import Section定义了从外界宿主环境导入到模块对象中的资源,而Export Section则反向导出资源到外部宿主环境。了解Wasm模块的二进制组成结构有助于开发者更深入地了解浏览器引擎在处理和使用Wasm模块时的内部工作方式。Wasm模块文件的头部数据由特殊含义的字节组成,包括“魔数”和版本号,用于判断文件是否是合法的Wasm模块文件。文章还介绍了Wasm模块文件的具体二进制组成结构,以及Wasm模块中最为重要的“魔数”和“版本号”。每一个Wasm模块都由多个不同种类的Section组成,这些Section按照其专有ID从小到大的顺序被依次摆放着。除了专有Section,模块还可以通过Custom Section来支持一些自定义功能。最后,文章提出了一个思考题,要求读者了解ELF格式的Section结构,并谈谈它与Wasm Section在设计上的异同之处。整体而言,本文深入浅出地介绍了Wasm模块的二进制组成结构,为读者提供了对Wasm模块内部工作方式的深入了解。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《WebAssembly 入门课》
新⼈⾸单¥29
立即购买
登录 后留言

全部留言(12)

  • 最新
  • 精选
  • 能不能结合 wasm 的可识别文本 来讲解各个 section ? 这个干讲不是特别形象。 比如 使用 assemblyscript 编译后生成的 wat 文件

    作者回复: 嗯嗯,收到你的反馈了。主要是考虑到内容的先后顺序,所以这里还是选择从字节码的角度来介绍 Wasm Section 的组成结构。可以先有个大致印象,关于 WAT 的角度,在 06 中会提到哈。

    2020-09-11
    4
  • Twittytop
    我有一个疑问,如果一个整数经过编码之后还变大了,那为什么还要编码?为啥不用它原来的大小存储

    作者回复: 这是一个很好的问题。你可以设想一下,如果我不对这些数字值进行压缩的话,我在解码时如何知道这个给定的数字值有多长呢?假设一个 u32 类型的值,如果所有数字都按照 32 位完全展开的方式编码,那对于一个简单数字比如 2,我都需要在二进制格式里把它完全展开成 32 位,这样至少在解码时我才能知道那部分属于整个数字,哪部分是指令。但这种方式就会浪费很多空间,存在很多无意义的占位 0。但如果可以使用 LEB128 这类可变长编码对数字值进行编码,对这个数字的识别就会简单的多,并且也不需要完全展开再进行编码。当然即使有填充字节 0x80 \ 0xff 存在,这个编码也是合法的。

    2022-04-25
    1
  • AIGC Weekly 周报
    对于文中 c++ 编译成 wasm二进制文件,我的疑问在于每个 Section 具体内容的所占字节如何确定呢?我在官网上也没有找到相应的知识。作者能辛苦解答下吗?或者评论区的大佬指导下?

    作者回复: 关于 Section 的内部组成结构可以参考官方标准:https://webassembly.github.io/spec/core/binary/modules.html

    2021-12-12
    1
  • xiaobang
    table section 中如果存放的不是anyfunc,调用call indirect 会失败的吧

    作者回复: 是的,会抛出 Runtime Exception。anyfunc 作为一个类型,其具体形式是由宿主环境定义的,也就意味着在调用 call_indirect 的时候宿主环境会去检测 Table 中对应位置存放的值是不是可以被作为 anyfunc,如果不是则抛出运行时错误。当然,宿主环境也同样会阻止非 anyfunc 类型被存放在 Table 中。

    2020-09-13
    1
  • 忒亚
    这章好抽象

    作者回复: 有哪里没看懂吗?

    2022-06-12
  • 哄哄
    据我所知varint32编码的很小的整数仅占用一个字节。1和7编码后不应该是6个字节。

    作者回复: 具体看编译器,但都是合法的。 However, “trailing zeros” are still allowed within these bounds. For example, 𝟶𝚡𝟶𝟹 and 𝟶𝚡𝟾𝟹 𝟶𝚡𝟶𝟶 are both well-formed encodings for the value 3 as a u8.

    2021-05-29
  • champ
    最后那个例子里面的,payload_len为什么是由5个16进制表示? 我的理解是varuint32,不是应该有32bit,也就是4个16进制数字表示吗? 还有最后的紫色方块由6个16进制数字表示一个函数签名也不太明白

    作者回复: varuint32 表示的是被编码的数字本身可以表示为 32bit,并不是说编码的结果是 32bit。函数签名的部分可以对照上文给出的 Type Section 的组成结构进行分析。

    2021-01-17
    3
  • 大土豆
    ELF是和特定平台相关的二进制格式。WASM是一个通用的字节码格式,和平台无关,由浏览器的解释器执行
    2020-09-11
    14
  • 阿吉学习wasm
    ELF Section 和 Wasm Section 相同:都采用了线性结构,都有“魔数”和版本号等等。 不同点:ELF是有段和节的划分,多个节构成段。而WASM直接是段。
    2020-12-13
    3
  • 胖狐狸
    除了其中名为 “Custom Secton”->除了其中名为 “Custom Section” 发现一个typo
    2023-12-07归属地:广东
收起评论
显示
设置
留言
12
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部