指令集与处理器架构
无论什么编程语言编译生成的可执行文件(库文件),想要在CPU上执行, 就必须被翻译成机器码
, 翻译这个工作由编译器来执行, 编译器在这个过程中, 要经过编译
, 汇编
, 链接
几个步骤, 最后生成可执行文件或者库文件
. 可执行文件中保存的是二进制的机器码
, 这串机器码可以直接被CPU读取和执行.
指令集:当前CPU可以识别的所有机器码
的集合,称为指令集
- 当前主流的指令集有很多,比较常见的有:x86指令集, x86_64指令集,ARM指令集(ArmV1 - ArmV8 版本,当前还在不断完善迭代),RISC-V指令集、MIPS指令集等
CPU架构:基于某种指令集
设计出的CPU, 称为对应的架构; 例如:基于ArmV8指令集设计出的CPU,称为 ArmV8 架构,基于x86指令集设计的CPU,称为x86架构; 在大部分场合,架构等于指令集
指令集从广义上的分类有两种, 复杂指令集,精简指令集
复杂指令集(Complex Instruction Set Computer,CISC):
包含了大量的指令集。这些指令集能够完成复杂的操作,但同时也会导致设计复杂,功耗较高,基于复杂指令集设计的CPU通常使用在PC,笔记本等设备上,用做服务器,工作站等
精简指令集(Reduced Instruction Set Computer,RISC):
仅包含了必要的指令集。这些指令集虽然简单,但可以通过组合使用来完成复杂的操作,因此设计简单,功耗较低,基于精简指令集设计的CPU一般使用移动设备、物联网、嵌入式系统等功耗敏感和资源受限的场景
- 上文中提到的x86指令集就属于复杂指令集,ARM指令集、RISC-V指令集等,属于精简指令集分类
X86指令集(架构)及其历史
x86架构有为32位和64位两个版本;
x86是指Intel的开发的一种32位指令集,从386时代开始,一直沿用至今,是一种cisc指令集,所有Intel早期的cpu,以及amd早期的cpu都支持这种指令集,在Intel官方文档中称之为(IA-32),有时候也会被称为i386。
x86的32位版本最初被设计用来运行个人电脑等应用程序,其寻址空间为 4GB,可以使用 32 位指针寻址。随着应用程序变得越来越复杂和庞大,32 位处理器逐渐不能满足人们的需求。随着计算机科技的不断发展,人们对于计算能力和内存容量的需求越来越大,因此需要一种更高效、更强大的处理器来满足这些需求。
于是,x86指令集的64位版本,AMD64(由AMD制造和命名)和x86-64(也称为x64或Intel64或IA-64,由intel公司制造) 应运而生, x86_64和AMD64本质上是同一个东西,都是基于x86指令集的64位扩展,支持更大的内存地址空间和更高精度的计算。无论是从指令集还是硬件功能等方面来讲,它们都没有任何区别。 相较于 32 位版本,64 位版本可以支持更大的内存地址空间和更高的处理能力,其寻址空间为 18EB(1EB=1024PB),可以使用 64 位指针寻址。可以更好地满足大型数据库、图像处理、科学计算等需要大量计算和内存的领域的需求。
ARM架构
实际上,ARM架构也是存在32位和64位之分的。ARM公司在2001年推出了ARMv8-A架构,这是一种全新的64位架构,支持更大的内存寻址空间和更高精度的计算。
在此之前,ARM架构主要以32位为主,例如ARMv7-A架构就是一种典型的32位架构。不过需要注意的是,由于历史原因和市场需求等方面的考虑,ARM公司并没有像x86架构那样明确地将其32位和64位架构进行区分,而是将它们看作是一个整体中不同版本的演进。
因此,在ARM生态系统中,我们经常听到的是“ARM32”和“ARM64”这样的术语。其中,“ARM32”指的是基于ARMv7-A或者更早的32位架构,而“ARM64”则指的是基于ARMv8-A或者更晚的64位架构。
需要注意的是,虽然ARM32和ARM64都属于ARM架构,但它们的指令集和硬件架构有很大的差异,因此相互之间是不兼容的。在使用软件时,必须选择与处理器架构相对应的版本。
下面是一个常见架构名称的等价关系清单:
ARMv8
= ARM64
= AArch64
ARMv7
= armv7l
= ARM
x86_64
= x64
= amd64
x86
= x86_32
顺便一提:
在linux系统中,可以使用 uname -a
指令来查看当前CPU架构
在Windows系统中,可以在cmd
中使用echo %PROCESSOR_ARCHITECTURE%
查看系统架构
交叉编译
由于不同架构的CPU,是基于不同的指令集设计和制成的:
所以使用支持x86架构的编译器,编译生成的软件,是不能直接在ARM架构的CPU上运行的,因为它们的指令集和硬件结构有很大的差异,相互之间是不兼容的。
如果要将一个基于x86架构编写的软件移植到ARM架构设备上,就需要使用支持 ARM 架构的交叉编译器(注意,是支持ARM架构的交叉编译器,而非普通的支持ARM架构的编译器,因为普通的支持ARM架构的编译器只能在ARM架构的CPU上运行,无法在x86架构的CPU上运行)重新编译并生成适用于ARM架构的版本。
在x86架构的CPU上,使用支持ARM架构的交叉编译器来编译软件的过程,称之为交叉编译
交叉编译器
交叉编译器(Cross-Compiler)是一种能够在一种处理器架构上生成适用于其他不同处理器架构的机器代码的编译器。它通常由两部分组成:前端和后端。
前端负责将源代码转换为中间代码,同时对源代码进行语法检查、类型检查等操作。中间代码是与具体的处理器架构无关的,因此可以在不同的处理器架构上重复使用。
后端则负责将中间代码转换为目标架构的机器代码,并进行优化等操作。由于每种处理器架构都有其独特的指令集和硬件结构,因此需要根据目标架构的特性进行相应的调整和优化。
举个例子,如果我们想要在x86架构的CPU上编写一个适用于ARM架构的应用程序,就需要使用支持ARM架构的交叉编译器来生成适用于ARM架构的二进制文件。这个交叉编译器就包括了x86架构的前端和ARM架构的后端,可以将x86架构的源代码转换为ARM架构的机器代码。
交叉编译器的作用非常重要,它使得开发人员可以在自己的开发环境上进行开发和测试,而不需要在实际的目标平台上进行,从而提高了开发效率和便利性。