ARM64 的每条指令只有 32 位编码,却要搬动 64 位的数据和地址。这本书从这道自测题开始,用树莓派 4B 和 QEMU 搭台,把 ARMv8.6 的寄存器、页表、内存屏障拆成几十个能上手的实验,也顺手记下了那些会让板子当场死机的坑。
书的第一页不是序言,也不是目录。是一张自测卷,20 道题,每题 5 分,满分 100。第 1 题只有一句话:“A64 指令集支持 64 位宽的数据和地址寻址,为什么指令的编码宽度只有 32 位?”
这一问的狠处在于它不问你记不记得,它问你服不服气。你要拿 64 位去搬动整个世界,手里的铲子却只有 32 位宽。答案不在题干里,在后面的第 3 章到第 7 章:加载与存储、算术与移位、比较与跳转,以及那章被作者直接命名为“A64 指令集的陷阱”的东西。
第 2 题更不客气,四条 mov 指令一字排开,问你哪几条能执行成功、哪几条会失败:mov x0, 0x1234、mov x0, 0x1abcd、mov x0, 0x12bc0000、mov x0, 0xffff0000ffff。第 3 题给了一段 sbc x0, x1, x2,x1 是 3,x2 是 1,然后不告诉你进位标志的初值。你会在纸边上算,算到一半忽然发现,自己已经在跟机器的脾气打交道了。
这就是这本书的入场方式。它不先给你一段历史,不先给你一张架构图,它先给你一个会让你答错的题。作者在前言里写得很实在:“有不少读者面对 8000 多页的官方 ARMv8 体系结构手册感觉力不从心。”8000 多页,这是官方手册的体量,也是多数人退场的地方。这本书给出的替代方案是 23 章、几十个实验、一块树莓派 4B、一台 QEMU 虚拟机。定价 119.80 元。你可以在《ARM64体系结构编程与实践》的详情页里看到它的全套目录。
四个门牌号,四种权力边界
ARMv8 里有个东西叫异常等级,EL0 到 EL3,一共四级。多数教材会把它讲成一张表,背下来就行。但这本书把它讲成了一套秩序:每一级只看见自己该看见的地址空间,每一级有自己专属的栈指针,SP_EL0、SP_EL1、SP_EL2、SP_EL3,互不越界。
EL1:系统特权,通常用于操作系统内核。如果系统使能了虚拟化扩展,运行虚拟机操作系统内核。
EL2:运行虚拟化扩展的虚拟机监控器(hypervisor)。
EL3:运行安全世界中的安全监控器(secure monitor)。
ARMv8 体系结构允许切换应用程序的运行模式。如在一个运行 64 位操作系统的 ARMv8 处理器中,我们可以同时运行 A64 指令集的应用程序和 A32 指令集的应用程序,但是在一个运行 32 位操作系统的 ARMv8 处理器中就不能运行 A64 指令集的应用程序了。当需要运行 A32 指令集的应用程序时,需要通过一条管理员调用(Supervisor Call,SVC)指令切换到 EL1,操作系统会做任务的切换并且返回 AArch32 的 EL0,从而为这个应用程序准备好 AArch32 状态的运行环境。
这段文字里藏着一个非常漂亮的细节:处理器运行在比 EL0 高的异常等级时,可以把 EL0 的栈指针 SP_EL0 当成一个临时寄存器用——Linux 内核就是这么干的,它拿 SP_EL0 存放进程中 task_struct 数据结构的指针。一个本该属于应用程序的寄存器,被内核借来当记事本。你手里的每一行用户态代码,脚下踩的都是这样一层被精心挪用的地基。
如果你想把这个“分层”的模型再看一遍,可以去看看网络世界是怎么做的:协议栈一层套一层,每层只解析自己那一段包头,谁也别想看穿全部。《图解TCP/IP网络知识轻松入门》讲的是同一件事的另一个版本。层级不是为了复杂,是为了让每一层都能假装自己是唯一的一层。
一行汇编,能让树莓派 4B 死机
第 7 章的标题很短:A64 指令集的陷阱。底下的案例标题更短,也更像讣告:“案例 7-3:读写寄存器导致树莓派 4B 死机”“案例 7-4:LDXR 指令导致树莓派 4B 死机”。
这就是这本书最不肯装的地方。它没有假装汇编是一份可以优雅书写的诗。它直接告诉你,某几条指令写错了,板子就不动了。死给你看。这本书自称“总结了众多一线工程师在实际项目中遇到的陷阱”,这些案例就是那句话的兑现——不是隐喻,是物理意义上的黑屏。
更有意思的是它给实验留白的程度。“本书为了节省篇幅,大部分实验只列出了实验目的和实验要求,希望读者能独立完成实验。”换句话说,它不给你抄。第 8 章末尾排着“实验 8-1:汇编语言练习——求最大数”“实验 8-2:汇编语言练习——通过 C 语言调用汇编函数”,第 7 章末尾排着“汇编大作业 7-1:在汇编中实现串口输出功能”。你要自己去把那一行串口输出敲出来。
这种精度问题,其实和你家厨房里那张菜谱上写的“盐少许”是一回事:《“少许”是多少?两根手指捏起的量》里那两根手指,和这里一条指令装不下的那个立即数,都是同一个困境——量化的边界在哪里,手艺就在哪里。
把 8000 页折成 23 章和几十个实验
作者给这本书列了四条特色,第一条就是“突出动手实践”。这句话的兑现方式很具体:从第 2 章的实验 2-1 输出一句 “Welcome BenOS!”,一路往下,最终目标是“编写一个能在树莓派 4B 开发板上运行的简易的小型OS(具有 MMU以及进程调度等功能)” 。
从一行打印,到一个能管内存、能切进程的系统。这是这本书真正在卖的路线图。
它选的基础硬件也值得说一句。本书的实验环境是树莓派 4B,内置 4 个 Cortex-A72 处理器内核。Cortex-A72 是 2015 年发布的一个高性能处理器内核,“48 KB 的 L1 指令高速缓存以及 32 KB 的 L1 数据高速缓存”,L2 可配置为 512 KB、1 MB、2 MB 以及 4 MB,支持 48 个表项的全相连指令 TLB 和 32 个表项的全相连数据 TLB。你桌上那块巴掌大的板子,跑的是这套参数。
到了第 22、23 章,它开始谈向量计算:用 NEON 把 RGB24 转成 BGR24,做 4×4 矩阵乘法,再往上是 SVE 指令集和可伸缩矢量优化。这条线的另一端,就是今天所有在显卡和加速器上跑的东西。想看那个方向的完整推演,《深度学习与计算机视觉:核心算法与应用》是这一站的下一块路牌——同一批矩阵,换个语境继续乘下去。
它也不假装自己是孤岛。书里老老实实报出了自己依赖的东西:GCC 版本 9.3(aarch64-linux-gnu-gcc),QEMU 版本 4.2,GDB 用 gdb-multiarch 或者 aarch64-linux-gnu-gdb。配套的 QEMU+ARM64 平台支持 Linux 5.0 内核和 Debian 根文件系统。这些版本号看着枯燥,其实是作者在替你承担“我到底该装哪个”的麻烦。
先别读,先去把那四条 MOV 写完
如果这几分钟让你有点手痒,那么今晚只做两件极小的事。
第一件:找一张纸,把第 2 题那四条 mov 抄下来,每条后面画两个框,一个写“成功”,一个写“失败”,凭直觉打钩。不要查资料,不要问人。打完了把纸折起来收好。
第二件:打开终端,敲 sudo apt update -y,再敲 sudo apt install gcc-aarch64-linux-gnu qemu-system-arm。就这两个包,别的先不管。等它们装完,你已经站在实验 2-1 的门口了——那句 “Welcome BenOS!” 就在前面三步远的地方。
剩下的,交给第 3 章到第 7 章去回答你那张纸上的钩打得对不对。
书架上总有几本书是留着“以后再看”的,这本书可能是少数适合“现在就动手”的。它是硬核的、带刺的、会让你在纸边上算错再算一遍的。但如果你在这五分钟里,因为那四条 mov 忽然生出了一点“我想知道我猜得对不对”的痒——那么导游的活儿就干完了。
去吧,放下这篇文章。那张纸还空着呢。









