从x86到ARM,代码移植指北
Posted beyondma
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从x86到ARM,代码移植指北相关的知识,希望对你有一定的参考价值。
最近ARM架构的处理器从云到端全面开花,比如苹果MAC上的ARM架构处理器M1 MAX就堪称王炸,华为的鲲鹏系列ARM处理器也已经稳定服务了很长时间,目前业内有口皆碑,因此基于x86环境编写的程序也都需要考虑迁移到ARM架构上去,以适应扑面而来的ARM热潮。
针对这个迁移工作笔者进行了一些预研工作。从目前的情况看基于Java、Python等高级语言开发的程序是很容易移植的,问题的关键在于不少Java的包是调用C语言代码的,这时候就要考虑 .so 的动态库移植及内联的汇编语言移植,其中要点如下。
C语言移植要点
一.解决x86下unsign char问题
-1 的二进制原码是 10000001,它的补码是除了符号外取反加 1,最后补码就是 11111111。 在 x86 架构下,char 默认是有符号的,打印时输出为-1;但是在ARM架构下 char 默认是无符号的,这个二进制的 11111111 正好就是无符号的 255。 所以,出现这种情况的原因就是 x86 架构和ARM架构对于 char 的默认处理不一样,x86默认有符号的char类型,ARM默认无符号的char类型。
对于这种情况,有两种处理方式,一种是修改源代码,把数据类型指定为有符号型,另一种就是在编译时指定参数,把默认无符号型改成默认为有符号型,即在 gcc命令后面加入-fsigned-char 编译选项,示例如下:
aarch64-redhat-linux-gcc -fsigned-char -o transfer test.c
-
解决x86下值溢出
x86(指令集)中的浮点到整型的转换指令,定义了一个 indefinite integer value——“不确定数值”(64bit:0x8000000000000000),大多数情况下 x86 平台确实都在遵循这个原则,但是在从 double 向无符号整型转换时,又出现了不同的结果。 在这方面ARM的处理则非常清晰和简单,在上溢出或下溢出时,保留整型能表示的最大值或最小值,开发者并不会面对不确定或无法预期的结果。 double 型数据向 long 转换的结果对照如下:
CPU | double | 转为long | 变量保留值说明 |
x86 | 正值超出long | 范围0x8000000000000000 | indefinite integer value |
x86 | 负值超出long | 范围0x8000000000000000 | indefinite integer value |
ARM | 正值超出long | 范围0x7FFFFFFFFFFFFFFF | 变量赋值最大的正数 |
ARM | 负值超出long | 范围0x8000000000000000 | 变量赋值最大的正数 |
因此对于C语言的double型也需要着重对于indefinite integer value做溢出检查。
汇编语言移植要点
一.解决x86平台SSE、SSE2指令集的迁移问题
SSE、SSE2是x86平台上专属版权的单指令多数据流(SIMD)指令集的简称,SSE、SSE2与ARM架构的处理器上的SVE、SVE2对应。SIMD是指一条指令能处理多条数据,比如对于64位计算机来说,一条经典的指令输入、都输出只能是一个64位长的数据,针对双精度(128位长)类型的变量只能分解成若干个64位数据处理。而SIMD汇编指令可以提供由单一指令处理双精度变量的服务,其输入、输出由两个寄存器叠加组成。
目前针对x86的SSE指令向ARM的SVE汇编指令的迁移工作,已有开源项目可以实现全自动化迁移,项目下载地址:https://github.com/openestuary/sse2neon.git,使用方法如下:
步骤 1:将下载项目中的 SSE2NEON.h 文件拷贝到待移植项目中。
步骤 2 :在源文件中删除如下代码:
步骤 3: 在源代码中包含头文件 SSE2NEON.h。
二、解决x86平台XCHGL的迁移问题:
xchgl 是 x86 上的汇编指令,作用是交换内存变量的值,而且由于这是单指令操作,因此此操作属于原子操作。而ARM架构处理器上需要用glibc的原子操作接口__atomic_exchange_n 替换。
书籍推荐
在x86程序向ARM架构CPU的移植方面,笔者推荐《ARM嵌入式系统移植实战开发》,本书详细介绍了x86程序向ARM的移植,理论加上大量的实例,是ARM移植方面必备的工具书。
以上是关于从x86到ARM,代码移植指北的主要内容,如果未能解决你的问题,请参考以下文章