RISC指令集特点——以ARM为例
RISC指令集特点——以ARM为例
复习定位
RISC(精简指令集计算机)的设计哲学——简单指令、固定长度、大量的通用寄存器——让CPU容易实现流水线和高频率(或低功耗)。ARM是RISC的典型代表——控制ARM处理器。了解ARM的加载-存储体系——只有load/store指令访问内存——运算指令只操作寄存器。熟悉ARM指令格式有助于理解不同ISA的基本思想以及RISC和CISC的本质差异。
RISC的设计思想
RISC的核心原则(由Berkeley的Patterson和Hennessy总结):
- 简单指令——指令数量少且功能单一(如一条加法只是加法——不兼做从内存取数)——实现简单——硬件控制逻辑更紧凑更快速。
- 固定指令长度——ARM模式4字节、Thumb模式2字节——取指简单——不需要预译码探测指令边界——简化了流水线的取指阶段。
- 载入/存储结构——只有load(LD)和store(STR)指令可以访问内存——所有的算术逻辑指令只能在寄存器之间操作——这使流水线实现简单(因为运算指令不会在EX阶段需要第二次访存)。
- 大量通用寄存器——ARM有31个通用寄存器(X0-X30)加PC——寄存器多——编译器可以将更多频繁使用的变量放在寄存器中——减少对慢速内存的访问。
- 条件执行——ARM的大部分指令可以带条件执行——
ADDEQ R0,R1,R2仅在之前条件码判断相等(ZF=1)时才执行这一加操作——消除了流水线中分支执行的开销。
ARM的加载-存储示例
// C: a = b * 3 + c
// R0 = b, R1 = c (假设)
LDR R2, [R0] // R2 = *R0 (从内存地址R0处读取到R2)
LDR R3, [R1] // R3 = *R1 (R1的读取)
ADD R4, R2, R2, LSL #1 // R4 = R2 + R2*2 = R2*3
ADD R5, R4, R3 // R5 = R4 + R3 = b*3 + c
STR R5, [R0] // *R0 = R5 (写回内存)CISC指令集(x86)的对应操作可能一条MOV EAX, [EBX+ECX*2+4]完成——但一条复杂指令的执行可能需要多个时钟周期——而RISC的多条简单指令可能实现不到一条CISC指令执行完的时钟周期。
ARM的异常与中断
ARMv8的异常级别分为四个(EL0-EL3):EL0用户态运行普通程序——EL1运行操作系统内核——EL2运行Hypervisor——EL3运行安全监视器(Secure Monitor)。这是ARM在安全性和虚拟化方面为现代系统设计的特点。
中断响应——当外部中断到达——CPU切换到异常模式(IRQ/FIQ)保存当前状态——从中断向量表中取出入口地址——执行中断服务程序——用ERET(异常返回)指令恢复。
ARM与x86的关键对比
| 特性 | ARM (RISC) | x86 (CISC) |
|---|---|---|
| 指令长度 | 固定4B(ARM) | 可变1-15B |
| 寻址方式 | 少量(基址+偏移) | 多种(各种寻址方式) |
| 内存访问 | 仅LD/STR | 大多数指令可访问 |
| 通用寄存器 | 31个 | 16个(包括堆栈指针) |
| 条件执行 | 大多数指令可条件执行 | 大多数指令不可 |
| 功耗/面积 | 低(适合移动) | 高(高性能) |
复习检查
RISC强调"载入/存储结构"——为什么这简化了流水线的设计——因为运算指令不需要访问内存——流水线的EX(执行)阶段只做运算——不会因为等待内存数据而停顿。
ARM的31个通用寄存器比x86的16个多很多——这给编译器带来了什么好处——变量更有可能直接存放在寄存器中——减少栈内存的访问负载。
ARM条件执行是如何避免分支预测失败的——如果大部分指令都可以带条件执行——一个简短的if-else块可以被条件执行的指令序列替代——避免分支指令——从而避免分支预测失败开销。
ARM的异常级别(EL0-EL3)与x86的特权级(Ring 0-3)的异同——两者都支持多级隔离——但ARM的虚拟化(Hypervisor在EL2)和安全监控(EL3)是x86在后来才通过VMX(SMM)逐渐实现的。
为什么ARM能成为移动设备处理器的主导——低功耗IP授权模式、优秀的能效比(每瓦性能)——而Intel的x86在功耗方面的架构设计更适合桌面和服务器——但在移动设备上无法与ARM竞争。