计算机组成原理查漏补缺
三种指令类型 (R, I, J)
MIPS 指令集的设计非常整齐,所有的指令都是 32位(bits) 长。但是,这 32 个格子怎么分配,取决于指令的类型。
(1) R-type (Register type, 寄存器型)
- 用途:纯粹的数学运算。
- 特点:所有的操作数都在寄存器里。
- 例子:
add $t0, $t1, $t2(把 t1 和 t2 里的数拿出来相加,结果存到 t0)。 - 格局:因为它需要 3 个寄存器(2个源,1个目标),所以它的空间被切得很细,最后剩下了 6 位给
func。
(2) I-type (Immediate type, 立即数型)
- 用途:涉及常数运算,或者读写内存。
- 特点:操作数里包含一个具体的数字(立即数)。
- 例子:
ori $t0, $t1, 100(把 t1 和数字 100 做或运算)。lw $t0, 4($t1)(去内存取数,地址是 t1 + 4)。
- 格局:为了放那个数字(比如 100),它牺牲了
rd和func的位置,腾出了 16位 的空间来存这个数。
(3) J-type (Jump type, 跳转型)
- 用途:程序跳转(就像代码里的
goto)。 - 特点:跳得很远。
- 例子:
j 1000(直接跳到地址 1000 去执行)。 - 格局:除了开头的 op,剩下的 26位 全用来存目标地址,保证能跳得足够远。
| 指令类型 | 全称 (中文名) | 包含的常见指令 (加粗为你课件中的) | 核心特征 | 指令格式结构 (32位) |
|---|---|---|---|---|
| R-Type | Register Type (寄存器型) | add (加法) sub (减法) and, or, slt, nor | 纯运算。 操作数全在寄存器里,不做数据传输,不涉及立即数。 | op(6) rs(5) rt(5) rd(5) shamt(5) func(6) (特点:op全为0,靠 func 区分) |
| I-Type | Immediate Type (立即数型) | ori (或立即数) lw (加载字) sw (存储字) beq (相等分支) addi, andi, bne | 带常数/地址偏移。 计算或访存时,需要用到一个具体的数字(16位)。 | op(6) rs(5) rt(5) immediate(16) (特点:最后16位是常数/地址) |
| J-Type | Jump Type (跳转型) | jump (无条件跳转) jal (跳转并链接) | 长距离跑路。 不需要计算,直接跳到程序代码的另一个位置。 | op(6) address(26) (特点:后面26位全是目标地址) |
op 和 func 是什么?
这两个是指令的身份证。
op(Opcode, 操作码):指令的高 6 位 (31-26 bit)。- 作用:它决定了这到底是一条什么指令(大类)。
- 比喻:就像身份证上的“省份”。控制器一看
op,就知道你是lw还是sw还是beq。 - 特殊情况:对于所有的 R-type 指令,它们的
op都是000000。这就尴尬了,控制器光看op分不清你是加法还是减法。
func(Function code, 功能码):指令的低 6 位 (5-0 bit)。- 作用:专门用来区分 R-type 指令的具体操作。
- 比喻:就像身份证上的“名字”。
- 逻辑:当
op是000000时,控制器就会去查func。func = 100000-> 做加法 (add)func = 100010-> 做减法 (sub)
- 注意:只有 R-type 有
func。I-type 和 J-type 的这最后 6 位已经被那个常数或者地址占用了,所以它们没有 func 字段。

为什么对于所有的 R-type 指令,它们的 op 都是 000000
设计者回头看了一眼 R-type 指令的格式。他们发现了一个惊喜:
R-type 指令只需要存 3 个寄存器编号(rs, rt, rd)和 1 个移位量(shamt)。
op: 6位rs: 5位rt: 5位rd: 5位shamt: 5位- 总共使用:$6 + 5 + 5 + 5 + 5 = 26$ 位。
32 - 26 = 6 位!
R-type 指令的末尾,正好空出了 6位 没地方用。
天才的设计思路来了:
既然 R-type 指令末尾空着 6 位,那为什么不把 Opcode 统一设为 000000(意思是:这是一条运算指令),然后利用末尾这空闲的 6 位(也就是 func 字段)来具体区分是加法还是减法呢?
- 这样一来,
add,sub,and,or,slt等几十条运算指令,在 Opcode 表里只占用 1 个位置(就是 000000)。 - 这就把剩下的 63 个 Opcode 宝贵名额,留给了那些没有空闲位置的 I-type 和 J-type 指令(因为它们后面被立即数填满了,没有
func字段可用)。
控制信号的含义都有哪些
这些信号就是控制器发出的“命令”,控制数据通路里的多路选择器 (Mux) 和 使能开关 (Enable)。
我们把它们分为三类来记:
第一类:选路信号(Mux Selectors)
这些信号决定数据走哪条路。你可以理解为火车轨道的道岔。如果是 0 走左边,1 走右边。
RegDst(Register Destination)- 含义:运算结果存到哪个寄存器编号里?
- 背景:
- R-type 的目标寄存器编号在指令的第 15-11 位 (
rd字段)。 - I-type (如 lw) 的目标寄存器编号在指令的第 20-16 位 (
rt字段)。
- R-type 的目标寄存器编号在指令的第 15-11 位 (
- 值:
1: 选rd(R-type)。0: 选rt(I-type)。
ALUSrc(ALU Source)- 含义:ALU 的第二个操作数来自哪里?
- 值:
0: 来自寄存器堆的读出数据(两个寄存器做运算,如 R-type)。1: 来自指令里的立即数(寄存器和数字做运算,如ori,lw,sw)。
MemtoReg(Memory to Register)- 含义:写回寄存器的数据来源是谁?
- 值:
1: 来自内存的数据(只有lw指令是这样,把数据从仓库搬回寄存器)。0: 来自 ALU 的计算结果(绝大多数指令,如add,ori)。
第二类:开关信号(Enables)
这些信号是安全锁。只有设为 1,才允许动作。
RegWr(Register Write)- 含义:允不允许修改寄存器的值?
- 值:
1: 允许写。像add,lw,ori这种需要保存结果的指令。0: 禁止写。像sw(只是往内存存数),beq(只是比较),j(只是跳转),绝对不能改写寄存器里的数据。
MemWr(Memory Write)- 含义:允不允许修改内存的值?
- 值:
1: 允许写。只有sw(Store Word) 指令是 1。0: 禁止写。其他所有指令。
第三类:功能控制信号
ExtOp(Extension Operation)- 含义:16位的立即数怎么变成32位?
- 背景:指令里的数字只有16位,但计算器是32位的。
- 值:
1(Signed): 符号扩展。保持正负号不变(比如 -2 扩展后还是 -2)。用于lw,sw,beq(算地址偏移量)。0(Unsigned): 零扩展。高位直接补0。用于逻辑运算如ori。
Branch- 含义:这是一个条件分支指令吗?
- 值:如果是
beq指令,这个信号是1。它会结合 ALU 的“零标志位”来决定要不要跳。
Jump- 含义:这是一个无条件跳转指令吗?
- 值:如果是
j指令,这个信号是1。直接强行修改 PC 指针。
ALUctr(ALU Control)- 含义:ALU 到底做什么数学题?
- 值:这是个多位信号(通常3位或4位)。
Add: 加法 (用于add,lw,sw)Sub: 减法 (用于sub,beq比较是否相等)Or: 逻辑或 (用于ori)
什么是控制器 (Controller)?
在 CPU 这个“大工厂”里,主要分两部分:
- 数据通路 (Datapath):这是干活的工人和机器。包括寄存器(用来记账的小本子)、ALU(算盘/计算器)、内存(大仓库)。它们负责搬运数据、做加减法。
- 控制器 (Controller):这是工厂的指挥官。
控制器的作用: 它不直接干活(不存数、不算数),它的任务是看懂指令,然后对着数据通路里的各种开关“发号施令”。
- 输入:它看的是指令(Instruction)。比如指令说“把 A 和 B 加起来”,这串 0101 的机器码传给控制器。
- 输出:控制器根据指令,把相应的控制信号线拉高(置1)或拉低(置0)。
一句话总结:控制器就是 CPU 的大脑,它通过查表(真值表)来告诉身体的各个部位(ALU、寄存器、内存)在当前这一刻该干什么。
什么是数据通路 (Datapath)?
它的任务:根据指挥官(控制器)的命令,把数据从仓库(寄存器/内存)里搬出来,送到加工车间(ALU)算一下,再搬回去。
核心组成:
- 仓库:寄存器堆 (Registers)、数据存储器 (Data Memory)。
- 车间:算术逻辑单元 (ALU)、加法器 (Adder)。
- 交通枢纽:多路选择器 (Mux)、扩展器 (Ext)。
什么是单周期处理器 (Single-Cycle Processor)?
核心定义:CPI (Cycles Per Instruction) = 1。
通俗解释:
- 时钟信号“哒”(上升沿)一下,CPU 开始取指令。
- 在时钟“哒”下一响之前,CPU 必须把这条指令的所有工作(取指、翻译、运算、读写内存、写回结果)全部做完。
单周期处理器包含哪些功能?
为了让程序能跑起来,处理器通常需要支持三大类功能(指令):
A. 算术逻辑运算 (R-Type)
- 功能:做数学题。
- 指令例子:
add(加),sub(减),and(与),or(或),slt(比较大小)。 - 流程:读寄存器 -> ALU 算 -> 写回寄存器。
B. 数据传输/访存 (I-Type)
- 功能:搬运数据。CPU 的寄存器太小,数据多了要放内存里。
- 指令例子:
lw(Load Word):从内存搬到寄存器。sw(Store Word):从寄存器搬到内存。
- 流程:算地址 -> 读/写内存 -> (如果是读)写回寄存器。
C. 条件分支与跳转 (Branch & Jump)
- 功能:改变程序执行顺序(也就是改变 PC 的值)。
- 指令例子:
beq(Branch if Equal):如果两个数相等,就跳到某处去。j(Jump):无条件直接飞到某处。
- 流程:比较 -> 计算新地址 -> 修改 PC。
单周期处理器包含哪些组成部分?
我们可以把它分为“肉体”(数据通路)和“灵魂”(控制单元)两大部分。
第一部分:数据通路 (Datapath) —— “干活的”
这部分你之前的实验已经做了一大半了,现在需要补全:
- 取指单元 (Instruction Fetch) —— 这是新面孔
- PC (Program Counter):一个 32 位的寄存器,存着“现在执行到哪一行代码了”。
- 指令存储器 (Instruction Memory):存放你写的机器码的大仓库。
- 加法器 (+4):让 PC 自动加 4,指向下一条指令。
- 寄存器堆 (Register File)
- CPU 的“口袋”,这里有 32 个格子 ($0 - $31),用来存放临时数据。
- 算术逻辑单元 (ALU)
- CPU 的“计算器”,负责算加减法、逻辑运算。
- 数据存储器 (Data Memory)
- CPU 的“大仓库”,用来做
lw和sw。
- CPU 的“大仓库”,用来做
- 扩展单元 (Extender)
- 把 16 位的立即数变成 32 位。
- 多路选择器 (Mux) —— 交通警察
- 关键组件!比如
ALUSrc这个 Mux,决定了 ALU 的输入是来自寄存器还是立即数。
- 关键组件!比如
第二部分:控制单元 (Control Unit) —— “发号施令的”
在你上一个实验里,“你”就是控制器(手动在波形里设 0 或 1)。现在要写一个模块来替代你。
- 主控制器 (Main Control)
- 输入:指令的高 6 位 (Opcode)。
- 输出:所有的控制信号 (
RegDst,ALUSrc,MemWr等)。 - 作用:看到
lw指令,它就自动把MemtoReg拉高,把RegWr拉高。
- ALU 控制器 (ALU Control)
- 输入:主控制器的信号 + 指令的低 6 位 (Funct)。
- 输出:给 ALU 的
ALUctr(3位或4位)。 - 作用:专门告诉 ALU 该做加法还是减法。
MIPS是什么
1. 一种经典的 CPU 架构 (MIPS Architecture)
全称是 Microprocessor without Interlocked Pipeline Stages(无互锁流水线阶段微处理器)。
- 这是什么: 它是一种基于 RISC(精简指令集计算机)原则设计的 CPU 架构。
- 地位与影响: MIPS 是计算机体系结构教科书中的“标准模版”(著名的《计算机组成与设计》一书就主要使用 MIPS 教学)。它的设计非常简洁、优雅,对后来的 CPU 设计(包括 ARM 和 RISC-V)产生了深远影响。
- 应用场景:
- 曾经的辉煌: 索尼 PlayStation (PS1, PS2)、任天堂 N64 等游戏机都使用 MIPS 处理器。
- 现在的应用: 依然广泛用于路由器(如部分 TP-Link, Ubiquiti 设备)、嵌入式设备和部分龙芯处理器(早期的龙芯基于 MIPS 指令集)。
- 现状: 虽然曾经辉煌,但在移动端被 ARM 击败,在开源领域受到 RISC-V 的强烈冲击。MIPS 公司后来宣布将架构开源,随后又经历了多次收购和转型,目前已不再开发新的 MIPS 架构,转投 RISC-V 阵营。
2. 一种性能指标 (Million Instructions Per Second)
全称是 Million Instructions Per Second(每秒百万条指令)。
这是什么: 它是衡量计算机 CPU 运算速度的一个老式指标。
计算公式:
缺点: 这个指标在现代对比中往往被认为不准确,因此有时候被戏称为 “Meaningless Indication of Processor Speed“(处理器速度的无意义指标)。
- 原因: 不同的 CPU 执行一条指令所做的事情不同。例如,CISC(如 Intel x86)的一条复杂指令可能相当于 RISC(如 ARM)的 5 条简单指令。仅仅比较“每秒执行多少条指令”并不能真实反映两台不同架构电脑的快慢。
ISA是什么
ISA 是 Instruction Set Architecture(指令集架构)的缩写。
它是计算机体系结构中最重要的抽象层,可以理解为软件(程序员/编译器)和硬件(CPU)之间的“合同”或“接口”。
1. 核心概念:它是什么?
想象一下驾驶汽车:
- ISA 就像是驾驶舱的设计标准: 它规定了“方向盘是用来转弯的”、“右边的踏板是油门”、“仪表盘显示速度”。只要懂这个标准,你就能开福特,也能开丰田。
- 硬件(微架构)就像是引擎的设计: 它是 V6 还是 V8 引擎,是燃油还是电动,这属于内部实现。
在计算机中:
- 软件(操作系统、编译器)只看 ISA,它只需知道“发送
ADD指令能做加法”,不需要知道 CPU 内部是有几亿个晶体管怎么连线的。 - 硬件(CPU 设计师)必须实现 ISA 规定的所有功能,至于怎么实现(用多少级流水线、多大的缓存),那是硬件的事。
2. ISA 规定了什么? (CPU 的“词汇表”)
ISA 定义了程序员在汇编层面能看到的所有东西:
- 指令集 (Instructions): CPU 能干什么?(如:加法、减法、从内存读取数据、跳转)。
- 数据类型 (Data Types): 它是怎么理解 0 和 1 的?(如:这是个 32 位整数,还是个 64 位浮点数?)。
- 寄存器 (Registers): 程序员能直接控制哪些“临时存储格”?(比如 MIPS 里的
$t0-$t9,x86 里的RAX,RBX)。 - 寻址模式 (Addressing Modes): 怎么找到内存里的数据?(是直接给地址,还是通过寄存器加偏移量?)。
- 内存管理与异常处理: 程序崩溃了怎么办?如何和操作系统配合?
MIPS 指令集架构 (ISA)
MIPS 指令集架构 (ISA) 是计算机体系结构中最经典的“教科书级”设计。它基于 RISC(精简指令集计算机)理念,主打简洁、高效和规整。
以下是 MIPS 指令集的核心要素拆解:
核心设计理念
- 固定长度: 所有的指令都是 32位(4字节)长。这使得 CPU 解码非常容易。
- Load/Store 架构: 只有
load(读取)和store(写入)指令可以访问内存。其他的算术逻辑运算(如加法、减法)必须在寄存器之间进行。 - 三操作数格式: 大多数运算指令需要三个操作数(例如:
add a, b, c意思是a = b + c),非常直观。
Register Transfer Language(寄存器传输语言)
Register Transfer Language (RTL),有时在教科书中也称为 RTN (Register Transfer Notation),是一种用于描述计算机内部微操作 (Micro-operations) 的符号系统。
如果说汇编语言是给程序员看的,那么 RTL 就是给计算机架构师用来推导和设计电路逻辑的“数学公式”。它比汇编更底层,因为它描述的是数据在硬件连线上的具体流动。
以下是关于它的详细介绍:
核心符号 (The Vocabulary)
RTL 使用一套简洁的数学符号来表示硬件动作。掌握这些符号就能读懂各种架构图:
| 符号 | 含义 | 例子 | 解释 |
|---|---|---|---|
| $\leftarrow$ | 传输 / 赋值 | $R1 \leftarrow R2$ | 把寄存器 R2 的内容复制给 R1 |
| [ ] | 寻址 / 内容 | $M[100]$ | 内存地址为 100 的存储单元里的数据 |
| M | 内存 (Memory) | $M[PC]$ | PC 指向的内存地址里的内容 |
| , | 并行执行 | $R1 \leftarrow R2, R2 \leftarrow R1$ | 这两个操作在同一个时钟周期内同时发生 |
| () | 部分位 | $R1(0-7)$ | 仅操作 R1 寄存器的低 8 位 |