鲲鹏社区首页
中文
注册
开发者
使用DevKit迁移工具辅助汇编代码迁移

使用DevKit迁移工具辅助汇编代码迁移

DevKit软件迁移

发表于 2025/12/05

0

X86与ARM汇编代码差异

汇编代码介绍

作为计算机科学领域中最接近硬件底层的编程语言之一,汇编语言常被视为直接向计算机硬件下达指令的“母语”,其执行过程无需经过高级语言所需的复杂抽象与转换环节。与常见的高级编程语言不同,汇编语言与具体的计算机体系结构紧密绑定。

举例而言,基于 Intel 或 AMD 处理器的个人计算机通常采用 x86 或 x86_64 架构的汇编语言;而ARM 架构处理器,则依赖于 aarch64 等不同指令集。可以说,每种处理器架构都拥有其独特的“方言体系”。

尽管汇编语言在语法和编写方式上较为接近机器指令,学习难度相对较高,应用领域也较为专业,但它在现代计算系统中仍然具有不可替代的重要价值。其核心优势在于能够实现对硬件资源的直接与精确控制,从而绕过高级语言中可能存在的中间层与系统抽象,为程序提供极致的性能优化空间。在诸如图形渲染、操作系统内核开发、加密算法实现,以及对实时性、效率要求极高的嵌入式系统及高性能计算场景中,汇编语言依然发挥着关键作用。也正因如此,在许多追求极致性能的互联网的开源/自研项目中,经常能看到它的身影。

那么,在实际项目中,具体要如何使用汇编语言呢?它的“出场”方式其实很灵活,主要有这么几种:你可以只在关键地方嵌入一两句单条指令,就像在文章里引用一句点睛的诗词;也可以嵌入一小段多条指令,好比在段落中化用一个经典的典故;当然,你也可以直接编写一整个独立的汇编文件,这就如同创作一篇完整的古文了。

这种灵活性的背后,也带来了一个现实的挑战:正如不同地区有不同的方言,x86平台的“方言”(x86汇编)和鲲鹏平台的“方言”(aarch64汇编)语法截然不同。当需要把一个为x86平台编写的软件,迁移到鲲鹏平台上运行时,里面这些“方言”段落就成了必须翻译的难题。

好在,我们有专门的“翻译官”——DevKit迁移工具。它的一大亮点就是支持对x86平台高频汇编代码的自动转换功能,将x86汇编代码转换为鲲鹏汇编代码,让汇编代码的移植过程事半功倍。

Arm和X86汇编代码差异

不同CPU架构带来的指令集差异,导致软件切换CPU需进行迁移适配。具体体现在:

  • ARM:使用精简指令集(RISC),单指令实现任务最小化,处理器架构更为简化,拥有小体积、高效能的特性。
  • X86:使用复杂指令集(CISC),用最少指令实现特定功能,处理器架构复杂,单核性能较强。

他们在设计理念、指令数量、指令特征等方面都存在较大差异:

例如对于同一段C/C++程序代码,其在不同架构机器上的汇编代码有较大差异:

常用内嵌汇编指令迁移

常用内嵌汇编指令迁移方法

ARM的汇编语言与x86完全不同,需要重写,涉及使用嵌入汇编的代码,都需要针对 ARM进行配套修改。常见的内嵌汇编指令迁移包括:

1.基本操作指令(数据移动、算术运算)

以及一些项目中常用的指令:

2.内存访问指令

3.位操作指令(位测试与设置)

4.控制流与系统级指令

使用迁移工具完成内嵌汇编迁移

面对需要“翻译”的汇编代码,我们不必逐行手动查找。DevKit迁移工具会识别C/C++源码文件中的嵌入式汇编代码段,如果该汇编代码段属于x86汇编代码,则对于工具支持的转换场景,给出迁移建议。这些建议并非千篇一律,而是根据迁移建议场景分为几种情况:明确替换建议、增加头文件、模糊提示、无替换建议。使用汇编迁移工具前,需要使用者对汇编语言有简单了解,能根据指引完成汇编语句的修改。

明确替换建议

如果C/C++源码中存在内嵌汇编指令,则需要进行适配鲲鹏平台的兼容性修改,才能保证代码在鲲鹏平台正常运行。这种场景下,工具会提示用户在源代码中加上aarch64分支,将适配aarch64的等效汇编代码添加到aarch64分支内。例如:

需要修改为:

具体使用工具实操的扫描结果和替换结果如下:

嵌入式汇编扫描结果

嵌入式汇编自动修复结果

增加头文件

对于内嵌汇编内的汇编指令,如果包含一些特殊指令,例如“cpuid”指令,如果迁移到鲲鹏平台,需要添加头文件"KunpengTrans.h"才能保证工具转换后的内嵌汇编代码可以工作在鲲鹏平台上。在文件代码的最上方,加上如下语句块:

例如:

需要修改为:(在源码文件最上方添加如下代码)

源码对应位置代码修改为:

模糊提示

C/C++代码内嵌的汇编指令,在迁移到鲲鹏平台时,需要适配aarch64,工具对其中部分汇编指令不能做到代码的完美替换,需要用户根据工具识别的代码块,结合上下文和用户自己的汇编知识背景进行人工介入,判断是否可以直接使用工具给出的建议源代码。工具会建议用户加上aarch64分支,并将适配aarch64的汇编代码以注释的形式添加到aarch64分支内。需要用户根据迁移建议中的提示,结合上下文检查汇编代码,判断建议中的汇编代码是否可以直接在鲲鹏平台上使用。若用户判断可以直接使用,可将注释符号删除。在不确定的情况下,用户也可以先按照建议修改,手工编译,编译后再根据编译情况及功能测试情况进一步修改。例如:

需要修改为:

无替换建议

C/C++代码内嵌的汇编指令,在迁移到鲲鹏平台时,可能会有部分汇编指令是工具暂时无法提供替换建议的,此时工具会提示用户手动处理。对于暂时不支持提供可直接替换的代码,提示用户此处存在内嵌汇编需要修改,由用户自行判断和修改。例如:

提示修改如下:

note 1: The assembly code contains a global variable or global symbol, and cannot be automatically converted. Manually convert the code or modify the variable or symbol, and then convert the code again. See https://support.huaweicloud.com/ug-pa-kunpengdevps/kunpengpt_06_0126.html#section4 for reference.

由于%eax是x86专用寄存器,ARM架构没有eax寄存器导致无法自动完成修改。可尝试的修改方案例如:

通过这四种场景下的建议,迁移工具可以让我们在迁移汇编代码时有所参考,对于明确的替换建议和头文件替换可以快速完成适配;对于相对模糊的提示场景则更有挑战些,需要我们结合上下文提示和汇编知识,进行人工介入完成修改适配。

全汇编代码迁移

与内嵌汇编(Inline Assembly)不同,内嵌汇编代码通常是嵌入在C/C++函数中的 asm 代码块,而全汇编代码是完全由汇编语言编写的独立源文件(如.s或.asm文件)。这类代码不依赖于C/C++编译器的主流程,而是直接由汇编器(Assembler)生成目标文件。因此,内嵌汇编代码的迁移改动通常较小,局限于函数内的几个指令或段落;而全汇编文件的迁移则需要将整个文件,包括数据段、代码段、函数、指令等都从x86架构迁移到ARM架构,其迁移工作更为彻底和复杂,几乎等同于重写。

汇编源代码差异

由于x86和ARM架构在指令集、寄存器、寻址方式以及汇编器语法上存在根本性差异,一个为x86编写的汇编源文件无法被ARM平台的汇编器识别。其核心差异体现在以下几个方面:

1、指令集不同:这是最根本的差异。x86的mov, add, call, jmp等指令,在ARM64(AArch64)中都有其对应的但名称和语法不同的指令,如mov可能对应mov或ldr,call对应bl,jmp对应b等。

2、寄存器体系差异:x86使用如eax, ebx, esp等命名规则的寄存器,而ARM64使用x0-x30、w0-w30(64位和32位)的命名方式。函数调用约定(如参数传递、返回值存放的寄存器)也完全不同。

3、寻址方式不同:内存访问的寻址模式大相径庭。x86复杂的内存操作数寻址在ARM上通常需要通过单独的算术指令(如add)来计算地址,然后再通过ldr/str指令进行访问。

4、汇编器指令差异:控制汇编过程的伪指令也不同。例如,定义数据段、代码段、对齐方式等的伪指令在x86的汇编器(如NASM)和ARM的汇编器(如GAS)中语法迥异。

5、函数开头与结尾差异:在涉及栈帧操作的函数中,x86通常使用push ebp; mov ebp, esp来开始,而ARM64则可能使用stp x29, x30, [sp, #-48]!; mov x29, sp等方式。

使用工具辅助迁移

当项目中包含完全由x86汇编语言编写的独立源文件(如.s或.asm文件)时,我们也不必慌张,DevKit迁移工具(WEBUI版/IDE插件版)能够识别这些文件,并尝试将其转换为适用于鲲鹏平台(ARM64架构)的汇编代码。用户可以利用工具转换的结果对整个文件进行替换,使用前需要对汇编语言有简单了解,能根据指引完成汇编语句的修改,例如x86源代码文件test.s代码如下:

具体使用工具实操的扫描结果和替换结果如下:

在工具的帮助下,全汇编文件迁移的工作量能够得到极大的减少,结合开发者的专业知识和细致检查能够进一步地保证迁移地准确性。

参考学习

本页内容