鲲鹏架构入门与实战
上QQ阅读APP看书,第一时间看更新

5.1.3 应用需要迁移的原因

1.汇编代码角度

从5.1.2节的汇编代码分析可以看出来,同样的C语言代码,在编译成不同架构下的程序后,得到的汇编代码是不同的,这些不同点主要体现在以下3个方面:

1)处理器指令

以简单的给变量赋值操作为例:

(1)鲲鹏架构。

首先使用mov指令把操作数传送给寄存器,然后使用ldr指令把寄存器的值传送到内存。

(2)x86架构。

直接使用movl指令把操作数传送到内存。

鲲鹏架构和x86架构在具体的处理器指令设计上,是有重大区别的,同样的功能,两个架构的处理器指令实现的方式可能不一样。

2)寄存器

这一点也比较明显,两个架构下的寄存器不管是数量还是功能都有所不同。

(1)鲲鹏架构。

ARM 64有34个寄存器,其中编号x0~x29是通用寄存器,x30为程序链接寄存器,x31比较特殊,它有时候用作xzr零寄存器,有时候是栈指针寄存器sp,两者不能在一条指令里共存,另外两个寄存器是程序计数器PC、状态寄存器CPSR。

ARM 64寄存器x0~x30及xzr零寄存器都是64位的,它们的低32位构成了32位寄存器,分别用w0~w30表示,用wzr表示32位下的零寄存器。

除此之外,ARM 64还有浮点寄存器和向量寄存器,此处就不详细介绍了。

(2)x86-64架构。

x86-64架构下有16个64位的通用寄存器,这些寄存器支持访问低位,例如访问低8位、低16位、低32位。

16个寄存器的名称和用途如表5-2所示。

表5-2 x86-64寄存器用途

3)指令长度

x86下指令的长度是不一样的,短的只有1字节,而长的却有15字节,给寻址带来了一定的不便。

鲲鹏架构指令长度为固定的32位(ARM工作状态),寻址方便,效率较高。

2.计算技术栈角度

对于常用的使用高级语言编写的应用,计算技术栈一般分为两类,一类是编译型语言,另一类是解释型语言,这两种技术栈的示意图如图5-3所示。

1)编译型语言

编译型语言的代表是C/C++等语言,使用编译型语言编写的源代码经过一系列的编译过程,最终才能生成可执行程序,大体流程如图5-4所示。

图5-3 技术栈示意图

图5-4 C编译过程

因为不同架构下指令集不同,导致依赖于指令集的二进制机器码、汇编语言都不同,所以同一段程序,在不同的架构下,需要最终编译成和架构相适应的二进制机器码。这也就解释了5.1节最后两个实验不能成功的原因,毕竟架构不同,在特定架构下编译的二进制机器码,它需要执行的指令在另一个架构下根本就不存在。

2)解释型语言

解释型语言的代表是Java/Python等语言,从图5-3可以看出,Java的源代码会被编译成字节码,字节码运行在Java虚拟机JVM上,JVM具有与平台架构无关的指令集,同一段Java代码在不同的架构下都可以编译成相同的字节码。JVM对字节码进行解释,转换为物理CPU对应的机器码进行实际执行。因为不同的指令集架构可以适配不同的JVM实现,所以Java等解释型语言只需编译一次,就可以到处运行,不同架构下的JVM屏蔽了指令集之间的差异。

如果一个应用是使用纯Java语言编写的,理论上基本可以跨平台运行,但是实际情况比较复杂,有些Java应用会引用so库文件,这些so库文件很有可能是通过编译型语言例如C来编写的,这时候就要考虑so库文件的移植。