本节摘要:ARM 架构从 1985 年的 ARMv1 到今天的 ARMv9,指令集语法骨架几乎未动,演化都发生在"扩展"与"执行态"两个维度上。读懂版本号的规则与每代新增的扩展,就掌握了查询架构手册的索引——本节按时间线过一遍六代关键版本,并给出兼容性判断的实操规则。
第 2 章开头说,本章先看今天的版图、再回头讲它怎么长成这样——本节就是那趟回头路。先立一条主线:ARM 的演化不是换房子,而是不停加盖。1985 年确定的地基(加载存储、定长指令、条件执行)从未推翻,每一代只是在同一块地上加楼层:Thumb 指令集是一层,NEON 向量扩展是一层,安全扩展是一层,六十四位执行态是把整楼加宽了一倍。理解了"加盖"这个模式,版本号就不再是需要死记的编号,而是楼层索引。
1985 年 Acorn 公司造出第一颗 ARM 芯片时,根本没有资格谈向后兼容——它没有存量软件要养。这个"一无所有"成了 ARM 最幸运的设计起点:没有 16 位寄存器的包袱,没有段式内存的遗产,一张白纸上画出来的加载存储架构,让后续每代演化都能通过"扩展而非重写"完成。对照第 1 章讲过的 x86 兼容性神话——现代 Intel 芯片里至今跑着模拟八十年代实模式的微码——你会看到两种截然不同的演化策略:x86 用复杂度换连续性,ARM 用"执行态切换"换连续性。ARMv8 引入六十四位时,没有改造 AArch32,而是并列了一套全新的 AArch64 执行态,两态各用各的寄存器命名与指令语法,靠异常级别切换。这个决定当时被批评"不够兼容",事后看恰恰保住了两边的纯粹。
时间线上挑四个转折点细看,每个都对应一个今天的日常工具。
ARMv4T(1994):Thumb 诞生。 16 位宽的 Thumb 指令集为的是把代码密度压下来——那时片上 ROM 以 KB 计,密度就是成本。Thumb 的历史意义远超省内存本身:它确立了"同一处理器两套指令编码、运行时可切换"的模式,ARMv8 的双执行态设计正是这一模式的放大重演。
ARMv7-A(2005):扩展走向体系化。 这一代把扩展划分为 profile——A(应用)、R(实时)、M(微控制器)——并把 NEON 多媒体扩展、TrustZone 安全扩展、虚拟化扩展依次排上日程。今天你在手机芯片规格里看到的 Cortex-A 核心、TrustZone 安全区,都是这一代定下的框架。手推兼容性时的关键规则也来自这里:ARMv8 的 AArch32 态基本就是 ARMv7-A 的延续。
ARMv8-A(2011):六十四位的"并列新楼"。 新增 A64 指令集与 AArch64 执行态,寄存器从十六个宽到三十一个,指令从"几乎条条可条件执行"收敛为少数条件选择指令。注意它同时废掉了两样旧东西:IT 块(Thumb 的条件执行包装)与大部分逐指令条件化。判断兼容性的实操规则是:A64 与 A32/T32 互不兼容,混编必须经过执行态切换指令;而 ARMv7 用户态二进制可以不经修改跑在 ARMv8 的 AArch32 态下。
ARMv9-A(2021):安全与矩阵。 在 ARMv8 基础上引入机密计算架构(运行中的数据对同机其他软件加密隔离)与可伸缩矩阵扩展。指令编码与寄存器版图相对 ARMv8 几乎未动——又一次印证"加盖"模式。
工程上版本号最大的用途是当架构手册的目录索引。官方架构参考手册按"ARMv8-A 体系概览卷、A64 指令集卷、系统寄存器卷"组织,每条指令的说明页会标注"自哪个版本引入、属于哪个扩展"。拿到一段陌生汇编时的查证顺序是:先认执行态(A64 的 x 寄存器、A32 的 r 寄存器、T32 的混排宽度),再认扩展归属(带 v 前缀的多半是 NEON/浮点,msr、mrs 操作的是系统寄存器),最后按指令名查手册对应卷。
一个实用检查清单,写代码或读代码时按序自问:
-march=armv8-a 这样的字符串就是承诺的最低楼层;这四问的顺序也值得一记:先版本、再扩展、后兼容、终裁剪——从抽象承诺到具体芯片,一层层落地。
空口说"A32 代码能跑在 ARMv8 的 AArch32 态"不如验一次。用交叉工具链把同一段累加函数分别编成 A64 与 A32 两种目标,再看反汇编的差别:
aarch64-linux-gnu-gcc -O2 -c sum.c -o sum_a64.o arm-linux-gnueabihf-gcc -march=armv7-a -O2 -c sum.c -o sum_a32.o aarch64-linux-gnu-objdump -d sum_a64.o | head -20 # 看到的是 x 寄存器、四字节定长 arm-linux-gnueabihf-objdump -d sum_a32.o | head -20 # 看到的是 r 寄存器、可能带条件后缀
两个产物互为"外语":A64 产物里你找不到 r0,A32 产物里你找不到 x0。但如果把 A32 产物放到一台 ARMv8 手机上跑(系统以 AArch32 兼容态加载它),它原样工作——这就是"执行态并列"换来的连续性。变式:给 A32 编译加 -mthumb 开关再反汇编,你会看到指令流里混着两字节与四字节编码,这是 Thumb-2,第 3 章 3.3 节我们拿它做混编实验。
版本时间线理清了"楼层怎么加起来的",下一节进入今天的楼内——把三十一通用寄存器与系统寄存器的版图摊开细看。