【问题标题】:Difference between Assembler and Compiler汇编器和编译器之间的区别
【发布时间】:2018-10-05 09:15:04
【问题描述】:
我尝试学习 MIPS 汇编语言以更好地了解计算机的工作原理。我通常编写 Java 和 JS,我知道 Java 正在使用 编译器 来执行我的代码。在学习 MIPS 时,我遇到了 assembler 这个词。
它们的工作方式有何不同?
【问题讨论】:
-
Assembler 将assembly 转换为本地指令,其中汇编是一种通常与本地指令一对一映射的语言。编译器处理高级语言。这很像滤锅和筛子之间的区别——实际上是一样的,但用法不同。
标签:
assembly
compilation
mips
【解决方案1】:
编译器和汇编器都采用人类可读的文本并将其转换为特定格式的二进制对象。
区别主要在于:
-
细节的来源。
在编译器中,细节来自上面,来自它所针对的编程语言。
高级语言是抽象的,因为它们在设计时考虑到了抽象机器,它们隐藏了硬件细节。
编译器必须将抽象机器中的操作映射到目标机器(真实机器)中的操作。
在汇编程序中,细节来自下面,来自它所针对的ISA。
汇编是具体的(不是 100% 具体的,例如参见 Pseudo-instructions),它是特定 CPU 的操作码的助记符。
汇编器必须允许程序员像使用操作码一样使用助记符,因为目标是直接指示 CPU,因此在汇编指令和机器指令之间存在紧密的 1:1 映射。
-
复杂性
高级语言具有复杂的语法,往往与英语相似,编译器必须做的解析和映射非常复杂。
需要一个词法分析器/标记器和a parser 来创建一个AST,该AST 用于相应地生成机器代码,这需要在树的节点之间保持一个上下文。
我们还期望编译器优化 AST 和生成的代码。
Assembly 具有基于行的语法,词法分析器和解析器一次仅限于一行,并且通常可以结合使用智能表查找来完成。
没有复杂的状态管理。
几乎没有优化空间,也没有花哨的、难以实现的功能映射到机器代码中,实际上映射很简单,因为它已经由程序员完成。
Bot 编译器和汇编器需要支持某些对象和执行文件格式,因此会增加一些复杂性。
-
目标
编译器是一个工具,它实现了从用户那里抽象出硬件细节的目标,我们希望编写一个可以在理想情况下在任何硬件中运行的源代码。
当人们不想将硬件抽象出来,而是想充分利用其功能时,汇编器是一种非常方便的工具。
因此,汇编器将公开一组低级细节(例如段),而编译器将尝试隐藏这些细节。
我们可以将编译器想象成一个跟随烹饪收据的人,当它说“混合牛奶”时,人类必须实际使用正确的工具(木勺?),将其放入牛奶中并制作旋转运动。
这是一件复杂的事情。
装配工就像一个孩子,它不会理解“混合牛奶”,我们必须告诉它“从左边画出的木勺,它就像一根长长的木棍,末端有一个凸起的末端”,“用手握住容器”,“将木勺放入牛奶中 4-5 英寸深”,“绕圈,顺时针方向平稳,不要太快”,“重复 20 秒”。
这些是更容易解析的指令,同时允许讲师更好地控制整个操作,例如如果他们想改变勺子的深度。
那么为什么我们有汇编器呢?
因为我们需要一种精确生成机器指令的方法,我们可以为此使用编译器,使用特定的语言,但由于低级指令列表的结构远不如抽象操作,最后结果将是一个美化的汇编程序(或多或少就像拥有像 Git 这样的版本控制软件只是为了提交一个充满复制粘贴备份的工作目录)。
所以我们将它们分开:汇编器的简单结构,编译器的复杂语法。