字节码和汇编语言是一回事吗?

Are Bytecode and Assembly Language the same thing?

这个问题可能看起来很奇怪,但我仍在努力掌握虚拟机的概念。我已经阅读了几个答案,但我仍然不明白 Java 字节码(以及 MSIL)是否与汇编语言相同。据我所知,字节码和汇编都被编译成机器码,所以就抽象而言,它们处于同一级别,即比机器码高一级。字节码也只是一种汇编语言,即一种人类可读的机器代码形式。如果是,那为什么还要使用汇编语言呢?为什么不用字节码(可以跨不同机器移植)而不是汇编语言(特定于单一机器架构)编程?谢谢

没有

Java 字节码是二进制编程语言,在"human readable form"中不是33=] 来源形式本身。

汇编通常是目标机器实际指令的文本助记符,相互映射1:1,所以汇编源代码中的一条指令会直接翻译成一条机器码指令(虽然有些例外存在CPUs 和汇编程序,例如许多 RISC 汇编程序将根据需要将 "load register with immediate value" 翻译成多条指令 - 加载任何立即值,而本机代码只能加载特定位,你必须编写整个值由几条指令)。

Java 字节码与大多数 CPU 的机器代码相比是相当高级的抽象语言,指令和内存模型的重叠非常小。唯一的相似之处在于,字节码以二进制形式存储,就像机器码一样。


编辑:

JVM原则上是解释器,即。它将动态的字节码翻译成机器码。就是这样,在编译时由编译器在其他语言中完成。

现代 JVM 不是 classic 纯解释器,而是使用 "JIT" (Just In Time) 编译器将 java 字节码的小片段编译成本地机器码,就在前面它的执行,使用缓存来避免第二次编译已知的 .class 文件,并且还使用 运行 性能数据的时间跟踪来更好地指导 JIT 编译器,哪些字节码应该被大量优化(运行 经常或内部循环),应该尽快编译,而不关注性能。

因此,对于现代 JVM,很难谈论解释器,它是相当复杂的解决方案。 C# 甚至经常更进一步,有时会提供预编译为通用平台机器代码的二进制文件的一部分(字节码形式仅作为不常见平台的后备)。

None 这(甚至不相似)发生在机器代码中。它只是在 CPU.

上执行

汇编语言是一种 human-readable 文本语言,旨在 assembled 为二进制文件。每个源代码行直接映射到一个二进制输出块(例如一个 variable-length x86 指令),而不依赖于前面的行。 (我不确定Java bytecode asm是不是context-sensitive;我没用过)。

例如mov eax, 1234 assembles 到相同的 5 个字节,不管它周围有什么其他源代码行。 (当然,忽略命名常量和 assembler 宏)。

"assembly language"(描述 标签 wiki 的那个)的默认含义是 CPU machine-code 汇编语言,其中字节是 assemble输出文件中的 d 是某种 CPU / 微处理器的本机可执行文件的指令和数据。

存在其他类型的汇编语言,例如 java 字节码汇编,其中输出文件中的 assembled 字节采用 Java .class 格式,并且可以是运行 由 JVM。 (@Ped7g 的回答扩展了这一点,关于 JVM 如何在将 Java 字节码翻译成本机机器码时进行优化。这个过程绝对不像汇编。)

都是文本语言导致assembler到assemble字节到输出文件.


您可以使用汇编语言来处理任何类型的二进制文件格式,甚至 non-executable。一个简单的示例:位图 still-image 文件格式的汇编语言,您可以在其中为每个像素使用命名颜色(如 midnight blue)。 assembler 会将 assemble 位(而不是像普通汇编语言那样只有整个字节)放入输出文件。

在更复杂的情况下,您可以想象一种 H.264 汇编语言,您可以在其中使用文本语法来描述 headers 和每个宏块的编码。

在这种情况下,您将设计 assembler 以将 assembled 宏块数据最终 CABAC 或 CAVLC 压缩为比特流,而不是将其描述为汇编语言。它就像一个 x86 assembler 生成 gzip 二进制文件:assemble 到 deflate 流中。


汇编语言的一个关键特性是它非常接近machine-code格式,disassembler 可以将二进制文件转回看起来像什么的汇编语言首先是 assembled(但当然没有任何注释、标签名称或宏)。

这就是为什么 C 和 Java 被认为比 binary/assembly 它们的编译器输出的语言更高级。

我明白你的意思,如果你眯着眼睛让事情变得有点模糊,那么绝对是的。 JAVA 字节码和 Python 等价物以及 Pascal 和其他一些可能只是机器码定义,它们的编译器编译成该机器码。该机器代码在机器上本地运行。到目前为止,这些机器是虚拟的,而且可能永远都是虚拟的,所以这就是你从这里的其他人那里得到的反击。

汇编是人类可读形式的机器代码,其中的位和字节不易被我们读取但易于被机器读取。

JAVA,等等,机器代码部分只是另一个指令集,还有其他直接在硬件中实现的基于堆栈的指令集,它是指令集的一种非常简单的通用方法。但是它们有一些高级系统调用,甚至比 CISC 高得多,这就是在逻辑上实现它们的问题所在。甚至没有理由对类似的东西进行微编码,你处理它的方式是使用本机指令集(最有可能从非 JAVA 高级语言编译)创建虚拟机。

如果它真的只是另一个指令集,那么您绝对可以为此创建芯片。但即使可以,也不意味着我们应该放弃现有的所有其他指令集。对于初学者 JAVA 工具似乎以它们不优化为荣。所以你从慢程序开始,只会让它们更快一点。当本地硬件上的其他语言在资源和能源方面的成本要低得多时。发明者有这样做的愿望,并且让我们相信它发生了,ARM Jazelle 和其他人。在 ARM Jazelle 的例子中,芯片在逻辑中获取字节,但它在由本机代码组成的 table 中查找它们。声称支持 Jazelle 的 ARM 处理器是假的,因为您必须从 ARM 购买软件 blob 才能使其正常工作,而且任何数量的其他 JVM 实际上都比付费的 ARM Jazelle 软件更快、更高效(有时是免费的)。所以那是一次失败,而且还是假的。

是的,它是一种被编译成机器代码的语言。该机器代码在机器上执行。不同之处在于那些机器是虚拟的,没有在硅片中实现(就像在微编码处理器上实现的机器代码一样,(咧嘴笑)),而且很可能不会。

字节码和汇编语言不是一回事,但它们是紧密相关的东西。

字节码是一种类似于机器码的简化二进制语言。字节码规范描述了程序应该如何编码以确保虚拟机能够正确理解和执行它。以同样的方式,处理器规范描述了所谓的指令集架构 (ISA),它显示了程序应该如何编码为 binary 机器代码,以确保处理器能够正确理解和执行它。因此,字节码是一种机器友好程序以位序列形式表示的形式。

字节码的问题在于,它在对机器处理极为方便的同时,对人的处理又极为不便。汇编语言提供了基于文本的,因此人性化相当于字节码。实际上,汇编语言在二进制形式的字节码指令和它们的文本等价物之间建立了一对一的映射,为程序员提供了一种方便的方式来阅读、理解和编写特定字节码(针对特定处理器或虚拟机)的程序。换句话说,字节码和汇编语言都在相同的抽象级别上描述程序,但使用不同的术语。

字节码指令和汇编语言语句之间严格的 1 对 1 映射允许程序从二进制形式轻松明确地转换为文本形式,反之亦然。正如您可能注意到的那样,有一堆反汇编程序允许工程师通过将它们从字节码二进制转换为汇编语言文本来深入了解已编译的应用程序。

汇编文本到字节码的转换需要编译。但与高级编程语言相比,汇编文本的编译非常简单。汇编程序以逐条语句的方式使用程序文本。通常汇编语言指定每个语句必须放在单独的程序文本行中,因此,汇编程序逐行使用该文本。它从每一行中提取一系列单词和标点字符,忽略注释,并使用该组单词作为映射 table 中的键,以找到表示相同指令的等效二进制字节序列。该字节序列被放入程序的字节码中。实际上,为了消除与文本解析相关的开销,Java 使用字节码并且在 JITing 期间不直接从汇编文本编译机器代码。

此外,与高级语言相比,汇编语言编译字节码不需要复杂的语法(构建抽象语法树)和语义分析,也不需要对生成的字节码进行优化。与现代编译器相比,汇编器非常简单。与高级编程语言相比,汇编语言总是链接到特定的字节码,从而链接到特定的处理器或虚拟机。高级语言最初是作为程序可移植性的一种手段引入的,因此它们被设计得足够通用。相比之下,汇编语言的程序不是 portable,但另一方面,它们为程序员提供了对相应处理器或虚拟机的所有功能的完全访问权限,同时其中许多功能在高级语言。

Java 和 C# 等编程语言所采用的思想是保留高级语言的可移植性,同时最大限度地减少执行程序所需的 interpretation/compilation 开销。因此,他们使用虚拟机和字节码。

注意,同一个字节码可以被多种汇编语言支持,因为同一个字节码指令到对应的不同文本字符串之间可能存在多个一对一映射的字典。每种汇编语言都可以提供自己的单词序列变体,以二进制形式描述相同的指令。例如,看看 x86 汇编程序。 Intel 使用一种表示法,Microsoft 使用另一种表示法,最后 GNU 汇编器使用完全另一种表示法。但是它们都编译成相同的机器代码。