目标代码、机器代码和汇编代码有什么区别?
你能举一个直观的例子来说明它们的区别吗?
机器代码是可以由 CPU 直接执行的二进制(1 和 0)代码。如果您在文本编辑器中打开机器代码文件,您会看到垃圾,包括不可打印的字符(不,不是那些不可打印的字符;))。
目标代码是尚未链接到完整程序中的机器代码的一部分。它是构成完整产品的特定库或模块的机器代码。它还可能包含在已完成程序的机器代码中找不到的占位符或偏移量。链接器将使用这些占位符和偏移量将所有内容连接在一起。
汇编代码是纯文本和(在某种程度上)人类可读的源代码,大部分具有直接的 1:1 模拟与机器指令。这是使用实际指令、寄存器或其他资源的助记符来完成的。示例包括用于 CPU 的跳转和乘法指令JMP
。MULT
与机器代码不同,CPU 不理解汇编代码。您可以使用汇编器或编译器将汇编代码转换为机器代码,尽管我们通常认为编译器与从 CPU 指令进一步抽象的高级编程语言相关联。
构建一个完整的程序涉及用汇编或更高级别的语言(如 C++)为程序编写源代码。源代码被汇编(对于汇编代码)或编译(对于高级语言)为目标代码,各个模块链接在一起成为最终程序的机器代码。在非常简单的程序的情况下,可能不需要链接步骤。在其他情况下,例如使用 IDE(集成开发环境),链接器和编译器可以一起调用。在其他情况下,可能会使用复杂的make脚本或解决方案文件来告诉环境如何构建最终应用程序。
还有一些行为不同的解释语言。解释语言依赖于特殊解释程序的机器代码。在基本级别,解释器解析源代码并立即将命令转换为新的机器代码并执行它们。现代解释器现在要复杂得多:一次评估整个源代码部分,尽可能缓存和优化,以及处理复杂的内存管理任务。
最后一种类型的程序涉及使用运行时环境或虚拟机。在这种情况下,程序首先被预编译为较低级别的中间语言或字节码. 字节码然后由虚拟机加载,即时将其编译为本机代码。此处的优势是虚拟机可以利用程序运行时可用的优化以及针对特定环境的优化。编译器属于开发人员,因此必须生成可以在许多地方运行的相对通用(优化程度较低)的机器代码。然而,运行时环境或虚拟机位于最终用户的计算机上,因此可以利用该系统提供的所有功能。
其他答案很好地描述了差异,但您也要求提供视觉效果。这是一张图表,展示了他们从 C 代码到可执行文件的过程。
汇编代码是机器代码的人类可读表示:
mov eax, 77
jmp anywhere
机器码是纯十六进制代码:
5F 3A E3 F1
我假设您的意思是目标文件中的目标代码。这是机器代码的一种变体,不同之处在于跳转是参数化的,以便链接器可以填充它们。
汇编器用于将汇编代码转换为机器代码(目标代码) 链接器链接多个目标(和库)文件以生成可执行文件。
我曾经用纯十六进制(没有可用的汇编程序)编写了一个汇编程序,幸运的是,这可以追溯到古老的(古老的)6502。但我很高兴有奔腾操作码的汇编程序。
8B 5D 32
是机器码
mov ebx, [ebp+32h]
是组装
lmylib.so
包含8B 5D 32
是目标代码
尚未提及的一点是,有几种不同类型的汇编代码。在最基本的形式中,指令中使用的所有数字都必须指定为常量。例如:
1902 美元:BD 37 14:LDA 1437 美元,X 1905 美元:85 03 美元:STA 03 美元 1907 美元:85 09 美元:STA 09 美元 1909 美元:CA:DEX $190A: 10 : BPL $1902
上述代码位,如果存储在 Atari 2600 磁带中的地址 $1900 处,将显示从地址 $1437 开始的表中提取的许多不同颜色的行。在某些工具上,输入地址以及上一行的最右边部分,会将中间列中显示的值存储到内存中,并以以下地址开始下一行。以这种形式输入代码比输入十六进制要方便得多,但必须知道所有内容的精确地址。
大多数汇编器允许使用符号地址。上面的代码会写得更像:
彩虹lp: lda ColorTbl,x STA WSYNC 斯塔哥伦布 索引 bpl Rainbow_lp
汇编器会自动调整 LDA 指令,使其引用映射到标签 ColorTbl 的任何地址。与必须手动键入和手动维护所有地址相比,使用这种类型的汇编器可以更轻松地编写和编辑代码。
源代码、汇编代码、机器代码、目标代码、字节代码、可执行文件和库文件。
对于大多数人来说,所有这些术语通常都非常令人困惑,因为他们认为它们是相互排斥的。查看图表以了解它们的关系。下面给出每个术语的描述。
人类可读(编程)语言的指令
用高级(编程)语言编写的指令,
例如 C、C++ 和 Java 程序
用汇编语言(一种低级编程语言)编写的指令。作为编译过程的第一步,高级代码被转换成这种形式。它是汇编代码,然后被转换为实际的机器代码。在大多数系统上,这两个步骤是作为编译过程的一部分自动执行的。
例如,program.asm
编译过程的产物。它可以是机器码或字节码的形式。
例如,file.o
机器语言指令。
例如,a.out
可以由解释器(如 JVM)执行的中间形式的指令。
例如,Java 类文件
链接过程的产物。它们是可以由 CPU 直接执行的机器代码。
例如,.exe 文件。
请注意,在某些情况下,包含字节码或脚本语言指令的文件也可能被视为可执行文件。
一些代码出于不同的原因编译成这种形式,例如可重用性和以后由可执行文件使用。
汇编是人类可以理解的简短描述性术语,可以直接翻译成 CPU 实际使用的机器代码。
虽然人类可以理解,但汇编程序仍然是低级的。做任何有用的事情都需要大量的代码。
因此,我们改为使用更高级的语言,例如 C、BASIC、FORTAN(好吧,我知道我已经过时了)。当编译这些产生目标代码。早期语言将机器语言作为其目标代码。
今天的许多语言,如 JAVA 和 C#,通常编译成不是机器码的字节码,而是一种在运行时很容易被解释以产生机器码的字节码。
我认为这些是主要区别
可读性可以在代码创建 6 个月后改进或替换代码,另一方面,如果性能很关键,您可能希望使用低级语言来针对您将在生产中拥有的特定硬件,因此要获得更快的执行。
IMO 今天的计算机足够快,可以让程序员通过 OOP 获得快速执行。
程序的源文件被编译成目标文件,然后链接器将这些目标文件链接在一起,生成一个包含架构机器代码的可执行文件。
目标文件和可执行文件都涉及架构的机器代码,当它被文本编辑器打开时,它以可打印和不可打印字符的形式出现。
尽管如此,文件之间的二分法是目标文件可能包含未解析的外部引用(例如printf
,例如)。因此,它可能需要链接到其他目标文件。也就是说,需要解析未解析的外部引用,以便通过与其他目标文件(如 C/C++ 运行时库的链接)获得体面的可运行可执行文件.