指令格式、寻址方式、CISC(x86)/ RISC(ARM/RISC-V)的根本分歧——ISA 这份「软硬件合同」(第 1.2 节)怎么写。
一条指令 = 操作码(opcode) + 地址码(操作数)。按操作数个数:
| 格式 | 形式 | 特点 |
|---|---|---|
| 三地址 | add a, b, c | a = b + c,直观但指令长 |
| 二地址 | add a, b | a = a + b,结果覆盖一个源(x86 主流) |
| 一地址 | add a | 隐含累加器 ACC(老式机器) |
| 零地址 | add | 隐含栈顶(JVM 字节码) |
指令长度是核心权衡:定长(RISC-V/ARM 均 32 位)解码简单、利于流水线取指;变长(x86 1~15 字节)编码密度高、但解码器逐字节判边界,是取指负担。
操作数藏在六种地方(记 EA 为有效地址):
| 寻址方式 | 指令例子 | EA / 操作数 | 用途 |
|---|---|---|---|
| 立即 | add r1, #5 | 操作数在指令里 | 常量 |
| 寄存器 | add r1, r2 | 操作数在寄存器 | 最快,最常用 |
| 直接 | ld r1, 0x1000 | EA = 0x1000 | 访问全局变量 |
| 寄存器间接 | ld r1, (r2) | EA = r2 | 指针解引用 |
| 变址 | ld r1, 0x100(r2) | EA = r2 + 0x100 | 数组 a[i]、结构体字段 |
| 基址+变址 | ld r1, (r2, r3) | EA = r2 + r3 | 二维数组 |
| 相对 | jmp target | EA = PC + 偏移 | 分支跳转 |
对比:寻址方式几乎一一对应 C——寄存器间接=指针、变址=
base+offset(a[i]/struct.field)、相对=if/goto。
注意:RISC-V 只有 4 种寻址方式,x86 有十几种(含
(%rbx,%rcx,8)基址+变址×比例)。寻址越多单条越强(CISC 一条mov干完取数+加+乘),但解码越复杂、越难流水化。
根源在「复杂度放软件还是硬件」:
| 维度 | CISC(x86) | RISC(ARM / RISC-V) |
|---|---|---|
| 指令长度 | 变长(1~15B) | 定长(32 位,ARM 有 16 位 Thumb) |
| 指令数量 | 数百上千 | 少而精(RISC-V 基础仅 ~40 条) |
| 寻址方式 | 十几种 | 3~4 种 |
| 访存 | add 可直接读写内存 | 只有 load/store 访存(load-store 架构) |
| 寄存器 | 少(x86-64 通用 16 个) | 多(RISC-V 32 个) |
| 实现 | 复杂解码器,常微码化 | 硬布线,易流水 |
| 代表 | 桌面/服务器 | 移动/嵌入式/新兴 |
RISC:每条指令简单、等长、单周期,复杂度交给编译器——换流水线好做、主频高、功耗低。CISC:一条指令多做点事,省指令数、省内存带宽,代价是解码难。
对比:RISC 赢移动端,CISC 守桌面/服务器。现代 x86 表面 CISC,内部把复杂指令译码成 RISC 风格**微操作(µop)**再执行;ARM/RISC-V 靠定长吃满流水线红利。故「CISC vs RISC」边界早已模糊,真正决定性能的是微架构(第 5、6 章)。
| 特性 | x86-64 | ARM (AArch64) | RISC-V |
|---|---|---|---|
| 设计者 | Intel/AMD | Arm 公司(授权) | 开源社区 |
| 长度 | 变长 1~15B | 定长 32 位 | 定长 32 位(可扩展 16/48) |
| 寄存器 | 16 通用 + 标志位 | 31 通用 + 零寄存器 | 32 通用 + 零寄存器 x0 |
| 条件执行 | 标志位 + 条件跳转 | 部分条件执行(CSEL 等) | 无标志位,比较+分支 |
| 授权 | 封闭 | 需授权费 | 免费开源 |
| 生态 | 桌面/服务器霸主 | 手机/嵌入式 | 正在扩张 |
注意:RISC-V 的
x0硬连线到 0——写被丢弃、读得 0,省掉「清零指令」,且作基址让ld a0, 0(x1)天然变直接寻址;ARMxzr同理。这是 RISC 用「特殊寄存器」替代「额外寻址方式」的手法。
mov rax, [rbx+8]、lea rax, [rbx+rcx*4]。