异架构相关
环境搭建
qemu 仿真
QEMU(Quick Emulator) 是一个开源的通用虚拟化和仿真框架,该框架主要有如下分类:
qemu-user:提供用户态的简单仿真。适用于对一些相对简单程序的进行仿真。qemu-system:提供完整的系统级仿真。例如有些固件的运行需要一整套复杂的环境,单纯使用qemu-user仿真比较麻烦并且容易出问题,因此一个比较简单的方法是把整个 IOT 设备的文件系统扔到对应架构的一个完整虚拟机中然后chroot切换到 IOT 设备的文件系统的根目录进行仿真,此时需要使用qemu-system运行整个虚拟机。qemu-utils:qemu 的一些配套工具,比如制作磁盘镜像的qemu-img。
安装命令:
1 | sudo apt install qemu -y |
qemu-user
qemu-user 是 QEMU 的用户态仿真组件,用于在宿主机(例如 x86_64 Linux)上直接运行其他架构(如 ARM/MIPS/RISC-V)的用户态二进制程序。该组件只仿真用户空间指令,不包括系统级仿真,因而被仿真的二进制程序的系统调用由宿主机内核负责。
安装与使用
qemu-user 组件可以单独安装,安装命令如下:
1 | sudo apt install qemu-user qemu-user-static -y |
qemu-user 的基本命令格式如下:
1 | qemu-<arch> [options] <target_program> [args...] |
例如:
在 x86_64 上运行 ARM 二进制
1
qemu-arm ./hello-arm
在 x86_64 上运行 RISC-V 二进制并传递参数
1
qemu-riscv64 ./hello-riscv arg1 arg2
常用参数
qemu-user 支持一些特定参数:
-L <path>:指定目标程序依赖的根文件系统(sysroot)。适合动态链接二进制。
例如:1
qemu-arm -L /path/to/armfs ./hello-arm
注意
有些依赖特定动态库和特定路径的固件程序需要通过
chroot将根目录切换到解压出的文件系统根目录然后再用qemu-user仿真程序,如果使用动态链接的qemu-user仿真会因根目录切换而无法找到qemu-user本身所依赖的动态库进而导致仿真失败,因此需要使用静态编译的qemu-user-static。-strace:输出系统调用日志,调试用:1
qemu-arm -strace ./hello-arm
-g <port>: 开启gdbserver,进行远程调试:1
qemu-arm -g 1234 ./hello-arm
-cpu <model>:指定仿真 CPU 型号:1
qemu-arm -cpu cortex-a9 ./hello-arm
-E VAR=value:向目标程序注入环境变量。
binfmt
在 Linux 内核中,binfmt(binary format)机制负责决定“某个可执行文件被执行时应由谁来解释 / 运行”。通过配置 binfmt,我们可以“透明”地执行异架构的二进制程序,而不用显式的通过 qemu-user 执行。
这一能力的核心子系统是 **binfmt_misc**。加载 binfmt_misc 模块后,内核会在 /proc/sys/fs/binfmt_misc/ 目录下暴露一组伪文件,用户空间通过向这些文件写入配置即可把“文件格式 → 解释器”映射关系注册给内核。
qemu-user 在安装时会在 /proc/sys/fs/binfmt_misc/ 路径下添加 binfmt_misc 相应的配置文件。因此我们直接运行异架构程序 Linux 会选择正确的 qemu-user-static 程序运行。
1 | ➜ ~ cat /proc/sys/fs/binfmt_misc/qemu-arm |
然而对于动态链接的程序,qemu 可以正常加载程序,但是动态库却会默认使用本机的动态库导致程序崩溃,因此需要 -L 参数指定 ld 的前缀径。另外如果将交叉编译工具链添加到对应的 qemu-binfmt,则 qemu-user 在运行程序时能加载正确的动态链接库,不需要指定路径。
1 | sudo mkdir /etc/qemu-binfmt |
qemu-system
qemu-system 仿真需要提供系统内核和文件系统,我们可以在这个网站下载所需结构的内核和文件系统。
qemu-system 启动命令如下,具体启动参数还要参考镜像对应的 README 作相应的调整。
1 | qemu-system-arm \ |
-M malta:主板类型,参考内核镜像后缀。-kernel vmlinux-3.2.0-4-4kc-malta:内核镜像。-hda debian_wheezy_mipsel_standard.qcow2:虚拟磁盘镜像。-initrd initrd.img-3.2.0-4-versatile:一个临时的文件系统映像,用于在Linux系统引导过程中提供必要的文件和工具,它通常用于初始化和准备真正的根文件系统之前。-append root=/dev/sda1 console=tty0: 内核启动参数。-net nic:添加一个网络接口卡(NIC)到模拟器中,以实现网络功能。-net tap,ifname=tap0,script=no,downscript=no:添加一个 TAP 设备,并将其与模拟器中的网络接口卡关联起来,用于与主机的网络进行通信。-nographic:禁用图形界面输出,只使用命令行界面进行连接和操作。
为了能够与 qemu 虚拟机通信,需要再 qemu 虚拟机启动先在外部主机创建并配置网卡 tap0 。
1 | sudo apt install uml-utilities |
qemu 虚拟机启动后需要再虚拟机中分配 ip 。
1 | ifconfig eth0 192.168.2.2/24 |
之后就可以通过 scp 向虚拟机传文件或者 ssh 登录虚拟机。
1 | sudo apt install sshpass |
交叉编译
交叉编译工具链
对于一些简单情形的交叉编译,直接下载对应的交叉编译工具链即可。
1 | sudo apt install gcc-arm-linux-gnueabi g++-arm-linux-gnueabi -y |
crosstool-ng
crosstool-ng 是一个 跨平台交叉编译工具链自动生成器。它通过一套脚本 + Kconfig 菜单界面,自动下载、打补丁、配置并编译 Binutils、GCC、C 库及调试工具,最终生成可重复使用的交叉编译环境(<triplet>-gcc、<triplet>-gdb 等)。
crosstool-ng 安装
在安装 crosstool-NG 之前,可能需要在宿主操作系统上额外安装若干软件包。这里我们可以参考项目中对应系统的 Dockerfile,例如 Ubuntu 22.04 需要安装如下依赖:
1 | sudo apt-get update |
之后将 crosstool-ng 项目克隆下来:
1 | git clone https://github.com/crosstool-ng/crosstool-ng |
克隆后须先执行 bootstrap 生成 configure:
1 | cd crosstool-ng && ./bootstrap |
之后编译安装即可:
1 | ./configure --prefix=/usr |
构建交叉编译工具链
这里以 x86-32 架构为例。
提示
由于构建整个工具链的过程受众多依赖种类、版本等影响,因此只能通过排列组合探索出一种可行的方式,并不能保证这个配置方式是最简的。
ARM
ARM 版本体系
ARM的版本体系可以分为三个层次:
- 架构版本(ISA) :这是 ARM 处理器的核心指令集架构,决定了处理器如何执行指令、如何与内存交互。
- 核心版本(Core) :基于架构,ARM 会设计具体的处理器核心,比如 Cortex 系列、Neoverse 等。
- 平台和产品系列 :ARM 设计的不同平台解决方案,比如面向移动设备的平台,面向服务器的 Neoverse 平台等。
ARM 架构版本(ISA)
ARM的架构版本是ARM处理器指令集的基础,从 ARMv4 开始,到现在的 ARMv9 ,ARM经历了几个大的变革:
| 架构版本 | 发布年份 | 特点 | 代表性产品 |
|---|---|---|---|
| ARMv4 | 1994 | 初代架构,支持32位指令集,主打低功耗嵌入式应用。 | ARM7TDMI |
| ARMv5 | 1999 | 加入了增强指令集,优化了性能,支持更高效的指令执行。 | ARM9 |
| ARMv6 | 2001 | 引入了Thumb指令集(16位指令,减小代码体积),支持更复杂的缓存系统。 | ARM11 |
| ARMv7 | 2005 | 分为A/R/M三种子架构,支持硬件虚拟化、浮点运算、SIMD等功能,支持Thumb-2(16/32位混合)。 | Cortex-A8, Cortex-A9 |
| ARMv8 | 2011 | 支持64位架构(AArch64),引入了64位寄存器和指令,提升了性能和寻址能力,同时保持向下兼容32位。 | Cortex-A53, Cortex-A57 |
| ARMv9 | 2021 | 强化了AI加速、安全(TrustZone增强)和虚拟化功能,同时优化了指令集。 | Cortex-A510, Cortex-A710, Neoverse V1 |
其中 ARMv8 架构在引入 64 位计算时,增加了 AArch 作为区分不同指令集架构模式的标识,提出了 AArch32 和 AArch64 两个明确的模式:
- AArch32:保持与 ARMv7 及之前架构兼容,支持 32 位程序执行,且继续支持 Thumb模式(16位指令)和 ARM模式(32位指令)。
- AArch64:是 ARMv8 引入的 64 位指令集,处理器支持 64 位寄存器(X0-X30),支持更大的寻址空间,且指令集被简化为统一的 32 位宽度指令(没有 Thumb 模式)。
ARM核心版本(Core)
ARM 设计了多个处理器核心系列,用于满足不同的应用需求。每个核心基于一个架构版本,提供了不同的性能、功耗、特性。
| 核心系列 | 说明 | 代表核心 |
|---|---|---|
| Cortex-A系列 | 高性能,面向应用处理器,支持运行操作系统(Linux/Android等),适用于手机、平板、笔记本等设备。 | Cortex-A7, Cortex-A9, Cortex-A53, Cortex-A72, Cortex-A76, Cortex-A78 |
| Cortex-R系列 | 实时处理器,强调低延迟和高可靠性,广泛用于汽车、工业控制、实时系统等领域。 | Cortex-R4, Cortex-R5, Cortex-R7 |
| Cortex-M系列 | 超低功耗微控制器,适用于嵌入式系统、物联网、传感器控制等。 | Cortex-M0, Cortex-M0+, Cortex-M3, Cortex-M4, Cortex-M7, Cortex-M33 |
| Neoverse系列 | 针对数据中心、云计算、服务器市场设计,优化了AI和高吞吐量任务。 | Neoverse N1, Neoverse V1 |
ARM 平台和产品系列
ARM 不仅设计了核心,还根据市场需求推出了各种完整的系统平台解决方案。这些平台集成了 ARM 处理器、GPU、内存、I/O 等组件,形成一个完整的 SoC(System-on-Chip)方案。
| 平台 | 说明 | 代表平台/产品 |
|---|---|---|
| ARMv7-A/ARMv8-A平台 | 移动和消费电子产品,支持高性能处理器、图形、音视频处理等。 | Apple A系列,Qualcomm Snapdragon |
| Neoverse平台 | 针对数据中心、云计算、边缘计算等市场设计,提供高性能的ARM处理器,优化了AI计算、并行处理和高吞吐量。 | AWS Graviton,Ampere Altra |
| Automotive平台 | 针对汽车电子、自动驾驶提供优化的处理器和系统方案。 | ARM Cortex-A系列在车载系统中的应用 |
| Arm Total Compute平台 | 针对智能终端设备(手机、平板、嵌入式设备)提供的完整系统平台,集成CPU、GPU、AI加速器等。 | Arm’s solution for mobile devices |
ARM32
寄存器
通用寄存器
| 编号 | 约定名 | 典型角色(AAPCS/EABI 主流) | 保存约定 |
|---|---|---|---|
| r0–r3 | — | 参数 1–4、返回值(r0;64 位返回用 r0–r1),临时值 | 调用者保存(caller‑saved) |
| r4–r11 | —(r11 常作 FP) | 被调方可保留使用的通用寄存器;有的编译器把 r11 当 帧指针 FP | 被调保存(callee‑saved) |
| r12 | IP(Intra‑procedure scratch) | 过程内临时寄存器;链接器 veneer/PLT 经常用它做跳板/中转 | 调用者保存 |
| r13 | SP | 栈指针(各异常模式多数都有独立的 r13,见 1.3) | 特殊 |
| r14 | LR | 返回地址(BL/BLX 写入);函数若继续 call 他人应先入栈保存 |
特殊 |
| r15 | PC | 程序计数器。读到的是“当前指令地址 + 偏移”(ARM≈+8,Thumb≈+4);写入=跳转/切态 | 特殊 |
r9(SB/平台寄存器):AAPCS 指定 r9 可作为“平台寄存器”,常被某些平台/工具链拿来充当 GOT/小数据静态基(SB) 或 TLS 指针(具体由平台约定)。在很多 Linux/EABI + 现代 GCC/Clang 的 PC 相对/PIC 代码里,r9 可能空闲,但也可能被用作 GOT 基址。
程序状态寄存器 CPSR
条件标志:
N(负),Z(零),C(进位),V(溢出),Q(饱和)。控制位:
T(Thumb 状态标志;1=Thumb,0=ARM);E(端序;1=BE,0=LE,平台固定/受控);A/I/F(禁用异步中止/IRQ/FIQ);GE[3:0](SIMD 比较分组结果);IT域(Thumb 的IT块状态);M[4:0](处理器模式位)。
访问:
MRS/MSR CPSR;异常模式还可MRS/MSR SPSR。
浮点/向量寄存器(VFP/NEON)
VFP/NEON 统一寄存器文件:
- Q0–Q15(128 位)↔ D0–D31(64 位)↔ S0–S31(32 位)三套视图互相重叠。
- 有的实现只有 D0–D15(VFPv3‑D16)。
硬浮点 ABI(armhf)保存约定(AAPCS):
- 被调保存:
D8–D15(即S16–S31/Q4–Q7涉及到的片段)。 - 其余(
D0–D7、D16–D31)调用者保存。
- 被调保存:
参数/返回:硬浮点下,浮点参数优先走 s/d/q;返回用
s0/d0(或q0某视图)。
汇编指令
调用约定
参数寄存器:
r0–r3;多余参数走栈(按 4 字节对齐)。返回:
r0(64 位放r0–r1;结构体可能经隐藏指针)。易失/保存:
- caller‑saved:
r0–r3、r12;VFP 的D0–D7、D16–D31; - callee‑saved:
r4–r11(以及 VFP 的D8–D15)。
- caller‑saved:
栈:满递减(向低地址生长),跨调用点需 8 字节对齐。
系统调用(Linux):
r7 = NR;r0..r6 = args;svc 0(返回在 r0,负值为 -errno)。Thumb 下 r7:某些编译器把 r7 用作 帧指针;若手写 syscall(
svc),要确保不与编译器的 r7 用途冲突(常用 内联汇编约束 或禁用 FP)。
其它特性
ARM64
寄存器
AArch64 共有 31 个 64 位通用寄存器:x0–x30(32 位别名为 w0–w30),外加**栈指针 sp**(有 wsp 别名)与不可直接寻址的 pc。
通用寄存器
| 范围 | 名称 | 角色(要点) |
|---|---|---|
x0–x7 |
参数/返回寄存器 | 函数前 8 个整型/指针参数与返回值使用;caller-saved(被调用者可破坏)。 |
x8 |
间接结果位置寄存器 (IRL) | 当返回“大对象/结构体”时,调用者把返回缓冲区地址放在 x8 传给被调函数;此外在 Linux 系统调用里,x8 还装系统调用号(与 C 调用约定无关)。 |
x9–x15 |
临时(scratch) | caller-saved,函数内部临时值。 |
x16–x17 |
IP0 / IP1 | “过程内调用临时寄存器”,可被链接器的跳板/PLT veneer使用;在普通代码里也可做临时,但要知道随时会被尾调用/跳板改写。caller-saved。 |
x18 |
平台寄存器 | AAPCS64 保留给平台约定:如果平台需要跨调用携带状态(如线程上下文),就用 x18;否则可作临时。可移植汇编最好避免使用。在 Apple 平台强制保留(不要用),Windows/ARM64也保留;Linux/ARM64通常当普通 caller‑saved 使用。 |
x19–x28 |
callee‑saved | 被调用者必须在返回前恢复它们(64 位全宽必须保留)。常用于保存长期活跃的局部变量/指针。 |
x29 |
FP(帧指针) | AAPCS64 允许作为通用 callee‑saved 或维持帧链;Apple 平台要求始终保持有效帧记录(便于回溯)。 |
x30 |
LR(链接寄存器) | BL/BLR 写返回地址到 x30;RET 从 x30 返回。调用者如需保留需入栈。 |
SP |
栈指针 | 16 字节对齐;只能在有限指令形态中参与(如 ADD/SUB (imm) 调整栈,或做访存基址)。**任何通过 SP 的访存都要求 SP % 16 == 0**。 |
XZR/WZR |
零寄存器 | 读恒为 0,写被丢弃;可作为算术“把结果丢弃/与 0 运算”的操作数。注意:编码上与 SP 复用寄存器号 31,具体解释取决于指令语境。 |
PC |
程序计数器 | 不可当通用寄存器直接读写;PC 相对地址由 ADR/ADRP 计算。 |
32 位别名(w0–w30)写入会把对应的 xN 高 32 位清 0(零扩展语义),很多时候你只需对 wN 写就相当于完成了零扩展。
x16/x17 可能被 PLT/Veneer 暂用,不要指望跨函数调用保存其内容(哪怕你没显式用它们)。
汇编指令
调用约定
C 调用:调用者把返回缓冲区地址放入 x8,被调用者把结果写回该地址后以“void”返回;这是 AAPCS64 的间接结果位置寄存器规则。
Linux 系统调用:参数 x0–x5,系统调用号在 x8,返回在 x0,通过 svc #0 进入内核。
1 | stp x29, x30, [sp, #-16]! |
MIPS
- Title: 异架构相关
- Author: sky123
- Created at : 2022-09-28 11:45:14
- Updated at : 2025-11-10 01:45:32
- Link: https://skyi23.github.io/2022/09/28/异架构相关/
- License: This work is licensed under CC BY-NC-SA 4.0.