译者:Mactavish (博主本人)
原文:https://hacks.mozilla.org/2017/02/a-crash-course-in-assembly
这是 “WebAssembly 以及为什么它这么快” 这个系列的第三部分。如果你还没阅读其他的部分,我们建议你 从头开始阅读。
理解 WebAssembly 是如何运行的,有助于理解什么是汇编以及编译器是如何产生汇编的。
在 关于JIT的这篇文章,我谈到了为什么机器沟通就像和外星人沟通一样。
我现在想看一下那个外星人的大脑是如何工作的,对于来自外界的通讯,机器的大脑是如何分析和理解的。
在它的大脑中,有一部分致力于思考——像是加减法或者逻辑操作。也有相邻的一部分提供短期记忆,然后还有另外一部分提供长期记忆。
这些不同的部分都有各自的名称。
-
思考的部分叫做算数逻辑单元 (ALU)。
-
寄存器提供了储存短期记忆的功能。
-
长期记忆就是我们所说的随机存储存储器 (RAM)。
机器码中的语句称之为指令。
当指令传递给大脑的时候,究竟发生了什么?指令会被分成几个不同的部分,这些部分有着不同的含义。
指令被切分的方式取决于大脑的布线。
打个比方,如果大脑是这样的布线,它很可能总是取前 6 个比特然后输送到 ALU 当中。根据 1 和 0 的位置,ALU 会计算并知道是要讲这两者相加。
这一块称作 “opcode” 也叫称作操作码,因为它告诉 ALU 要执行什么样的操作。
然后大脑会将之后的包含三个比特的两个块所代表的数字来相加。这些会决定寄存器的地址。
注意图上的机器码的注释,它有利于我们人类理解机器内部的运作。这就是汇编。它被称为符号机器码,是人类理解机器码的一种方式。
在这里你可以发现这个机器的机器码和汇编的最直接的关系。因此,对于不同的机器架构会有与之对应的不同的汇编。当你的机器内部有两种不同的架构,那么很有可能这台机器有它自己独特的汇编方式。
所以我们有可能面对着不止一个翻译目标。并不是说仅仅只有一种叫做机器码的语言,而是存在和很多不同的类型的机器码。就像我们人类说着不同的语言一样,机器也说着不同的语言。
当将人类的语言翻译成外形人的语言的时候,你可能会将英语,或者俄语,或者是普通话翻译成对应的外星语言 A 或者外星语言 B。而在编程领域,这就像将 C 或者 C++ 或者 Rust 转换到 x86 或者是 ARM.
如果你想要将这些高级编程语言向下转译为任何的对应不同架构的汇编语言。一种做法就是去创造一堆出不同的转换器,将它们一对一地转换成对应的汇编。
这么做显然效率不高。为了解决这个问题,大多数的编译在他们中间放置了最少一个中间层。编译器会将高级编程语言,转换为没那么高的级别,当然它也无法在机器代码这样的级别上运行。这称作中介表示 (IR)。
这意味着编译器可以将任何一种高级语言转换成 IR 语言。至此,编译器的另外一部分就可以将 IR 向下编译成特定的目标结构的代码。
编译器的前端将高级程序语言转换成 IR。编译器的后端将 IR 转换成特定目标结构的汇编码。
总结
这就是汇编以及编译器是如何将高级程序语言转换成汇编的。在 下一篇文章,我们会了解 WebAssembly 是如何适应这个体系的。
关于
Lin 是 Mozilla Developer Relations 团队的一名工程师。 She 专注于 JavaScript, WebAssembly, Rust, 以及 Servo,同时也绘制一些关于编码的漫画。