ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

零基础学ARM:核心概念、异常等级与第一条A64汇编代码

零基础学ARM:核心概念、异常等级与第一条A64汇编代码 简介这份PDF是周贺贺baron主讲的ARM进阶课程资料面向嵌入式软件工程师、BSP系统工程师、芯片软件工程师、Linux内核驱动工程师及安全架构师同时也适合学生从入门到精通、资深工程师查缺补漏。内容系统覆盖Armv8/Armv9架构核心模块ARM基础与A64指令集、异常中断与GIC、Trustzone安全架构、虚拟化、Cache、MMU、电源管理以及SoC架构设计课程强调异常中断是ARM架构的灵魂并对实际工程中最难排查的Cache一致性等问题作了重点讲解兼顾软硬件及大系统软件如Linux内核、ATF、OP-TEE、Secureboot的设计思想。整份PDF以白话通透的讲解和原创彩色框图著称可作为阅读15000多页ARM官方手册的高效导读材料。资源为1个PDF文件压缩包约7.22MB目前已有107人学习适合需要全体系掌握ARM架构、提升职场竞争力的技术人群。1. 先破解一个迷思手机里的 ARM 到底是什么你有没有过这种瞬间打开手机设置看到“处理器八核 ARM Cortex-A77”心里嘀咕一句“ARM 是什么东西能吃吗”然后关掉页面继续刷视频。不只是你很多写了三五年代码的工程师一提到 ARM 也是满脸“我知道它很重要但真让我说清楚它干了什么我有点虚”。我给你打个比方。如果把一台手机或一台服务器比作一栋楼操作系统是物业公司App 是住在楼里的住户那 ARM 就是这栋楼的承重结构——梁、柱、地基。你看不见它但整栋楼能不能盖高、能不能抗震、能耗高不高全由它决定。手机厂商拿到 ARM 的授权就像拿到一份建筑图纸可以按图纸盖楼也可以修改部分户型。全世界绝大多数手机、平板、路由器、电视盒子、智能手表甚至你车里的车机系统跑的都是这套 ARM 架构。这篇文章就是写给零基础新手的 ARM 入门扫盲。我会用大白话讲清楚 ARM 到底是什么、为什么值得花时间学、先学哪几个模块最后给你一条能实际走通的第一步路径。读完你会发现ARM 不是玄学它就是一套有规律可循的处理器设计规则而且这套规则离你的日常工作一点都不远。2. 先搞懂两个核心概念为什么异常等级是 ARM 的地基很多新手打开 ARM 手册第一反应是“字都认识连起来看不懂”。这是因为你还没建立 ARM 的核心心智模型。ARM 架构所有模块——内存管理、中断、安全、虚拟化——都是在两个核心概念之上搭起来的异常等级Exception Level和运行状态Execution State。这两个概念一通后面学什么都顺。2.1 异常等级处理器的“职级体系”想象一家公司。普通员工、部门经理、总监、CEO四个级别权力逐级递增能接触的信息也逐级增多。ARM 处理器内部就是这样的“职级体系”它叫异常等级Exception Level简写为 EL一共四级EL0 到 EL3。EL0 是最低权限跑的是你的 AppEL1 是内核级别跑的是 Linux 或 Android 的 KernelEL2 是虚拟化级别跑的是 Hypervisor虚拟机管理器EL3 是最高权限跑的是安全监控代码。每一级能干什么、不能干什么硬件上做了严格限制。EL0 的程序想直接改内存管理配置不行硬件直接拒绝必须通过系统调用“升级”到 EL1 让内核帮你做。这就像公司里普通员工不能直接进财务系统改工资必须走流程让 HR 处理。ARM 把这个“流程”设计成了硬件机制所以即使 App 出了 bug 想乱来也无法突破权限边界。这就是为什么我们说 ARM 架构本身就是安全的——它不是靠软件自觉而是靠硬件强制分级。在 Armv8/Armv9 里还引入了安全状态的概念区分安全世界Secure World和非安全世界Normal World。你的指纹信息、支付密钥存在安全世界普通 App 跑在非安全世界两者通过异常等级切换来通信。想深入了解 TEE、TrustZone必须先把 EL 的切换机制吃透。2.2 运行状态与 A64 指令集处理器“说”的语言除了职级ARM 还有自己的“工作语言”叫运行状态。Armv8 架构开始主要有 AArch64 和 AArch32 两种状态。AArch64 是 64 位状态手机里的现代 App 基本都是在这种状态下跑的AArch32 是 32 位状态主要为了兼容老软件。你可能听说过“A64 指令集”这个词。所谓指令集就是处理器能听懂的基本指令清单——加减法、跳转、读写内存都在清单里。A64 指令集是 AArch64 状态下使用的指令集每条指令固定 32 位。Armv8 刚出来时最有名的口号就是“A64 让 ARM 进入了 64 位时代”服务器芯片能跟 x86 掰手腕靠的就是这个。这里给你一个真实代码片段让你感受一下 A64 指令长什么样。这是最简单的“加一”操作// 伪代码把寄存器 x0 的值加 1再存回 x0 ADD x0, x0, #1就这么一行处理器就把 x0 寄存器里的数字加了一。别看简单任何复杂的程序——人脸识别、游戏渲染、密码学算法——最终都拆解成几亿条这样的基础指令。你不需要一上来记住所有指令助记符但要明白程序跑起来的过程就是处理器一条条执行这些指令的过程。2.3 异常中断与 GIC所有模块互相调用的“枢纽”在学习路径里我一直觉得异常中断Exception Interrupt是 ARM 的灵魂这一点必须强调。什么是中断就是处理器正在好好干活突然来了个紧急事件——网卡收到数据包、定时器到期、用户按了按键——处理器得停下来当前工作先去处理这个事件处理完再回来接着干。GICGeneric Interrupt Controller通用中断控制器是 ARM 用来管理这些中断的“总调度台”。一个 SOC 芯片里有几十个外设每个都可能随时发起中断GIC 负责决定先处理哪个、后处理哪个、哪个优先级更高、哪个中断要分给哪个核心。为什么说它是灵魂因为多系统之间的调用靠的就是中断。你的手机里同时跑着 Android 和 TrustZone 安全系统两个系统怎么切换不能直接跳转因为权限不同必须通过中断机制让高权限等级的中断服务程序介入完成切换。理解了中断你才能真正看懂 u-boot、ATF、OP-TEE 这些底层软件的运行逻辑——它们本质上就是个“中断处理大循环”。3. 别想一口吃成胖子ARM 学习的正确顺序很多新手拿到 ARM 资料包第一步就跑去啃 Cache 或虚拟化然后三天后放弃觉得“ARM 太难了”。我第一次学时也翻过车后来才悟到ARM 学习的本质是先建立全局地图再逐块攻坚。顺序对了事半功倍顺序错了寸步难行。3.1 先学 MMU 再啃 Cache性价比最高的路径如果让我给新手排一个学习顺序MMU 一定是“第一个攻坚目标”。MMUMemory Management Unit内存管理单元负责把虚拟地址翻译成物理地址。听着抽象但它其实是整个操作系统内存管理的地基。Linux 里的进程隔离、虚拟内存、内存映射文件全依赖 MMU。好消息是MMU 是 ARM 模块里最简单的一个。它核心就两件事——查页表、做权限检查。页表就是一张“虚拟地址 → 物理地址”的对照表。每次程序访问内存MMU 就查这张表找到对应物理地址。有些地址标记为“不可执行”那这段内存就只能存数据不能跑代码从而防止恶意程序注入。花一点时间把 MMU 学会你会瞬间理解 Linux 内核中很多原本“记不住”的知识点比如为什么每个进程都有独立的 4GB 地址空间、为什么内存碎片化是个问题。这些以前靠死记硬背的概念突然就有了画面感。学完 MMU 之后再攻 Cache。Cache高速缓存是 ARM 架构中最难啃的一块但又是工程中最常出问题的模块。工程师们常遇到的那些“超低概率但一出现就让人崩溃”的 bug80% 都和 Cache 相关——数据没刷出去、缓存没失效、多核之间数据不一致。你会在项目里听到一句经典吐槽“这问题怎么复现不出来一定是 Cache 的锅。”入门阶段你不需要把 Cache 的一致性协议全弄懂但要建立几个关键认知Cache 是 CPU 和内存之间的高速缓冲分 L1、L2、L3 多级Cache 何时写入内存、何时从内存读取有复杂的规则多核共享数据时要小心 Cache 一致性问题。知道这些你就不会在写驱动时“踩坑还不知道怎么死的”。3.2 TrustZone 与虚拟化带着安全视角学功力翻倍学 ARM 不学安全等于只学了一半。这句话我深表赞同。ARM 的 TrustZone 安全架构技术把处理器从物理层面分成了两个世界安全世界和非安全世界。你的指纹、人脸、支付密钥等敏感数据全放在安全世界里处理普通 App 跑在非安全世界即使被攻破也触及不到安全世界的数据。TrustZone 不是 ARM 的“附加功能”而是融入在每一个模块里。打开 ARM 手册你会发现MMU 有安全世界和非安全世界两套配置中断也有安全中断和非安全中断之分虚拟化更是分安全侧虚拟化和非安全侧虚拟化。所以学习任何 ARM 模块时都带着“这里安全世界怎么处理”的视角你的理解深度会完全不一样。虚拟化同样是 ARM 架构的重要组成。Elder 你可能觉得虚拟化是纯软件概念是 KVM、QEMU 这些软件的事。但在 ARM 体系里虚拟化是硬件设计的一部分。EL2 异常等级专门服务虚拟化让一个物理 CPU 能跑多个虚拟机每个虚拟机感觉自己在独占整台机器。有意思的是ARM 的虚拟化不止在普通世界有安全世界里同样存在这在汽车电子、云手机等场景中特别重要。3.3 建立全局观从 SOC 架构反推学习目标学完中断、MMU、Cache、TrustZone、虚拟化这些大件之后强烈建议你把视角拉高看整个 SOCSystem on Chip片上系统架构图。一个 SOC 芯片里除了 ARM 核心还有 GPU、内存控制器、各种外设控制器、总线互联等。打个比方ARM 核心是大脑总线是神经系统外设是五官四肢Power 电源管理模块是心脏供血系统。为什么要看 SOC 架构因为实际工程项目里你遇到的问题从来不是单一模块问题而是多个模块联动的问题。比如摄像头打不开可能是驱动写错了也可能和 GIC 中断配置有关还可能是电源管理没给摄像头供上电。你只有脑子里有整张 SOC 地图才能快速定位“这个问题该从哪个模块查起”。自学道路上你会遇到上万页的 ARM 架构参考手册。很多新手一打开 PDF 就晕因为不知道哪部分是当前要用的。你现在要做的是建立全局地图按需查阅而不是从头到尾读一遍。ARM 手册是工具书不是小说不需要通读但要熟练使用。4. 新手最容易栽的五个坑每条都是血泪经验ARM 自学路上很多坑是几乎人人都会踩一遍的。我把这些坑提前说给你能帮你少走不少弯路。以下五条都是我和身边的工程师朋友真实经历过的现在回想起来每条都疼。4.1 坑一一上来就精读 15000 页的 ARM 手册现象下单买了全套参考手册从第 1 页开始读读到第 100 页就放弃了觉得 ARM 根本不是人学的。原因ARM 架构参考手册是给“有具体问题需要查证”的工程师用的工具书不是新手教材。它默认你已经懂了计算机体系结构、操作系统、汇编语言没有这些基础直接读必然劝退。解决把手册当字典用。先跟着课程或教程搭建知识框架遇到具体问题时——比如“PSTATE 寄存器里的 DAIF 位到底怎么控制中断”——去手册索引里定位到对应章节精读那几页。这才是手册的正确打开方式。我第一次学时也犯过这个错后来被某位导师骂醒“你要查的是答案不是背诵全文。”4.2 坑二只会看代码不敢动手写汇编现象看别人分析 ARM 汇编代码时觉得“哦看懂了”轮到自己写时却连一条简单的加载指令都写不对。原因看代码是“被动理解”写代码是“主动构建”。ARM 汇编看起来指令不多但寻址方式、立即数范围、寄存器命名规则都有很多容易出错的细节看是看不出来的。解决哪怕是最简单的“点亮一个 LED”或“打印一串字符”也要亲手写一遍 aarch64 汇编代码然后编译、运行、调试。第一次写汇编你会觉得“这玩意儿怎么这么多约束”但跑痛几次之后这些约束就成了肌肉记忆。我给新人的建议是每个模块学完都写一个最小程序去触发它。比如学完 MMU就试着写一段代码切换页表学完中断就配一个定时器中断在中断处理函数里打印一条信息。4.3 坑三忽视异常等级切换程序跑飞了不知道怎么回事现象自己写了一个 EL1 下运行的小程序让它去访问一个只有 EL3 才能访问的寄存器结果程序直接死掉或者报错毫无头绪。原因ARM 对异常等级做了硬件级权限控制。低等级代码访问高等级资源时会触发异常或者直接被拒。很多新手没有这个意识以为“都是内存地址直接访问能有多大区别”。解决遇到访问异常时第一反应是检查自己在哪个异常等级、目标资源在那个异常等级。调试方法是在异常处理入口处打断点看异常向量表跑到哪里去了。我把这称为“ARM 调试第一直觉”只要程序莫名跑飞先查 EL 再查权限。这个习惯救了我无数次。4.4 坑四用 x86 的思维写 ARM 代码现象写代码时默认内存访问没有对齐要求或者默认整数溢出会自然进位结果在 ARM 平台上表现完全不一样。原因做了多年 x86 开发和 Linux 应用开发潜意识里已经把 x86 的特性当成了“所有 CPU 的默认行为”。ARM 在内存对齐、字节序、条件执行等方面跟 x86 有显著差异。比如 x86 允许非对齐访问代价是变慢而 ARM 在默认配置下遇到非对齐访问直接触发异常。解决学习 ARM 之前先有意识地清空“x86 惯性思维”。写驱动或裸机代码时遇到内存操作多问一句“这里是对齐的吗”“字节序对吗”。等你被非对齐访问的异常折磨过一次这个坑就彻底记住了。4.5 坑五只关注功能实现从不看 ARM 官方文档验证现象网上看到一段代码能跑通就直接用到项目里也不管它是否符合 ARM 架构规范。结果在某个特定芯片或特定配置下代码神秘失效。原因网上很多资料来自个人经验可能针对特定 SoC、特定内核版本有效但不具备一般性。ARM 的行为在不同版本Armv8.0 到 Armv9.x之间还有不少差异照着别人的经验抄容易翻车。解决遇到关键配置——特别是涉及安全、内存属性、缓存操作的代码——养成查官方文档的习惯。官方手册虽然难啃但它是唯一权威的“事实来源”。我自己的经验是先在网上找思路再去官方手册验证细节最后在硬件上实测。三步走完才算真正学会了一个知识点。5. 把第一条命令跑起来从读手册到写第一段 aarch64 汇编前面的概念讲再多都不如你亲手跑一段代码来得实在。这一章我会带你走一遍“从零在 ARM 平台上运行第一段汇编”的完整流程。你需要一台能跑 Linux 的电脑虚拟机也行云服务器也行有 ARM 开发板更佳但不强求。5.1 准备环境没有开发板也能学 ARM先说明一下如果手上没有 ARM 开发板完全可以用 QEMU 模拟器来模拟一个 ARM 环境。QEMU 是一个开源的硬件模拟器它能在一台 x86 电脑上虚拟出一颗 ARM 处理器你写的 ARM 汇编代码可以直接在上面运行。这就像你在自己没有 iPhone 的情况下用模拟器体验 iOS 系统——虽然性能有差距但学习足够。我建议你按这个顺序准备环境不用一次到位一台装了 Linux 的电脑Ubuntu、Debian 都可以没有的话虚拟机也行安装 QEMU 的 ARM 系统模拟模式安装交叉编译工具链aarch64-linux-gnu-gcc安装命令如下Debian/Ubuntu 系sudo apt update sudo apt install qemu-system-arm aarch64-linux-gnu-gcc两条命令分别做两件事第一条更新软件源第二条安装模拟器和交叉编译器。交叉编译器的作用是“在一个平台上编译生成另一个平台能运行的机器码”——你用 x86 的电脑编译出 ARM 处理器能跑的代码就靠它。5.2 写第一段 ARM 汇编让 GPIO 点亮一盏灯我们写一个“最 ARM”的入门程序控制 GPIO 点亮一盏 LED。在真实硬件上这需要查阅具体开发板的 GPIO 地址在 QEMU 里我们直接操作一个虚拟设备。不过为了让你看清 ARM 汇编的整个结构我先给出一个更底层的示例——一段纯粹的 aarch64 汇编在终端输出一条消息然后退出// 文件hello.S // 功能在 aarch64 下输出一行字符串并退出 .section .rodata msg: .asciz Hello, ARM Architecture!\n .section .text .global _start _start: // write(1, msg, 23) —— 向标准输出写字符串 mov x0, #1 // 文件描述符 1 stdout ldr x1, msg // x1 指向字符串地址 mov x2, #23 // 字符串长度 mov x8, #64 // 64 是 Linux aarch64 的 write 系统调用号 svc #0 // 触发系统调用进入内核态执行写操作 // exit(0) —— 退出程序 mov x0, #0 // 返回值 0 mov x8, #93 // 93 是 Linux aarch64 的 exit 系统调用号 svc #0 // 触发系统调用这段代码总共干了两件事向屏幕打印一句话然后正常退出。你已经发现ARM 汇编里“软中断指令 svc”是用来触发系统调用的关键指令。执行到 svc 时处理器会从 EL0 切换到 EL1进入 Linux 内核去完成实际工作。这就是前面说的“异常等级切换”第一次在你眼前活起来。接着我们把它编译并运行# 交叉编译成可执行文件 aarch64-linux-gnu-gcc -nostdlib -static hello.S -o hello # 用 QEMU 在用户态模式运行它 qemu-aarch64 ./hello你会在屏幕上看到一句Hello, ARM Architecture!。到这里你已经完成了一个完整的 ARM 汇编程序从编译到运行的全流程。这段程序里mov是赋值指令ldr是加载内存数据到寄存器svc是“系统调用”指令。核心逻辑就一句话把参数放进寄存器选好系统调用号触发 svc剩下的交给内核。5.3 参数怎么改三分钟学会自定义你的程序想试试改参数吗把字符串换掉、改长度就行。第一步把Hello, ARM Architecture!换成你的名字。第二步数一下新字符串有几个字符把mov x2, #23里的 23 改成新长度。然后重新编译运行。比如你想输出Hello, ARM World!18 个字符就把第 23 改成 18。看起来简单但它让你体会了一个 ARM 开发的核心规律一切操作都通过寄存器传参参数放好位置后触发一次“请求”剩下的由更高权限的软件完成。这个规律不只适用于系统调用在配置中断控制器、操作 MMU 页表、切换异常等级时全都是同一个套路。学会了这个思想你就抓住了 ARM 世界的钥匙。如果程序跑出来是乱码或者崩溃了九成是因为字符串长度算错了。这是个极其经典的初学者翻车点我当年也栽过。解决办法就一个字数清楚多一个字符都别放过。6. 下一步学什么给你一条可落地的进阶路线到这里你已经亲手跑通了第一条 ARM 代码证书有了。接下来怎么走我给你一条亲测有效的进阶路线按顺序积累每个阶段都有明确的“完成标志”这样你能实时知道自己到哪一步了。6.1 进阶四阶段从跑通到成为架构师我建议你把后续学习分成四个阶段每个阶段聚焦一个核心主题阶段主题完成标志建议周期第一阶段异常模型与中断能自己写一个 GIC 中断处理流程2-3 周第二阶段MMU 与内存管理能手动配置页表完成地址映射2 周第三阶段TrustZone 与安全能画出安全世界/非安全世界的通信流程3-4 周第四阶段大系统软件综合能通读 u-boot/ATF 的启动流程并解释每一步4-6 周第一阶段的关键是先把手头的定时器中断玩明白。定时器中断是 ARM 世界里最简单、最可控的中断源——它不需要外接硬件纯靠 CPU 内部定时器就能触发。你写一个程序设置定时器让它每隔一秒触发一次中断在中断处理函数里打印tick。这个过程帮你理解中断从发生、被 GIC 分发、到 CPU 跳转到异常向量表、再到处理完返回的全链路。第二阶段末期你会开始觉得“操作系统也没那么神秘了”。当你自己亲手配置过页表Linux 内核里那些mmap、页缺失异常、写时复制就不再是课本上的黑匣子。第三阶段的 TrustZone 学习建议找一款真实支持 TrustZone 的开发板树莓派 3 及以上都行体验一把在安全世界跑一个迷你 TEE OS 的感觉。别怕折腾这是从“写代码的码农”升级到“懂设计的架构师”的关键一跃。第四阶段则是收官之战。到这时你可以打开 u-boot 或 ATF 的源码顺着启动流程一路读下去从 BootROM 加载 BL1到 BL2 初始化 DDR再到 BL31 建立异常向量表并切到 EL2每一步都回想你之前学的知识点。你会发现之前学到的所有模块——中断、MMU、Cache、TrustZone——都能在这个启动流程里找到对应位置。6.2 学习资源与日常习惯长期坚持的秘诀除了上面的大课资源我再给你几个日常可用的学习方法每天抽出 30 分钟打开 ARM 架构参考手册读一小节哪怕只读懂一个寄存器的位定义也算收获。积累起来比周末猛学一天效果好得多。遇到新概念时先用自己的话写一段“我给朋友解释这个概念”的短文。写不清楚的地方就是你还没懂的地方。在群里或论坛上帮别人解答问题。回答问题的过程就是巩固记忆、发现盲点的过程。ARM 的学习很多时候是“教着教着就全会了”。如果条件允许买一块便宜的 ARM 开发板不用太高端。实打实在硬件上调试和只靠模拟器体验完全不同——模拟器不会让你体会到 Cache 一致性问题也不会让你遇到 GPIO 复用冲突的困扰。这条路走下来大概需要三到六个月。你不用急ARM 的学习没有“速成”这回事但它的回报是长期复利的。从那以后我每接触一个新的 SOC 平台都会强迫自己先用这套流程过一遍先看异常等级和启动流程再看内存映射最后看中断和 Cache 配置。这套习惯成了我的“条件反射”也让我从“天天被项目追着跑”变成了“开会时能给方案兜底的那个人”。现在这篇文章的使命已经完成了——你已经知道 ARM 是什么、为什么值得学、从哪里开始、第一个程序怎么跑通。剩下的路要从你动手写第一段汇编代码开始。希望这篇文章能帮到你。本文还有配套的精品资源点击获取
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表