软考中级嵌入式——第一章 计算机系统基础
1.数值转换
进位计数制系统基本概念
基本数码:
十进制 数码0-9
二进制 数码0-1
基数:
该进位制允许使用的数字符号的个数
十进制基数是10
二进制基数是2
位权:
一个数字符号在不同位置上所代表的固定倍数,通常写成 基数的某次幂(整数位从0次幂开始,小数位从-1次幂开始)。
例如十进制
123: 百位(1)的位权是 10^2=100 十位(2)的位权是 10^1=10 个位(3)的位权是 10^0=1数值 = 数码 × 对应位权,再求和:1×100+2×10+3×1=1231×100+2×10+3×1=123。
数的转换
R进制->十进制:按权展开法
604.01(八进制) = 6*8^2 + 4*8^0 +1*8^-2 (十进制)
十进制->R进制:短除法
整数部分除以基数,倒序取余数;小数部分乘以基数,正序取整数。
十进制 25 转二进制:除2取余 → 11001十进制 0.625 转二进制:乘2取整 → 0.101
2.数据的表示
2.1原码
原码Sign-Magnitude
最高位表示符号(0正1负),其余位表示数值的绝对值。最直观,但存在+0和-0的问题。
2.2反码
反码One's Complement
正数与原码相同;负数是对原码逐位取反(符号位不变)。同样存在±0问题。
2.3补码
补码Two's Complement (常用于加减法运算)
正数与原码相同;负数是反码末位加1。现代计算机普遍采用,可统一加减法运算。
2.4移码
3.计算机的组成
3.1冯·诺依曼体系结构
现代计算机几乎都遵循 冯·诺依曼结构,其核心思想是:
存储程序:指令和数据以二进制形式存放在同一存储器中。
顺序执行:CPU 从存储器中逐条取出指令、译码并执行。
基于此,计算机逻辑上分为五大部件。
计算机五大部件:运算器、控制器、存储器、输入设备、输出设备
其中 运算器 + 控制器 合称为 中央处理器(CPU),是计算机的“大脑”。
3.2五大核心部件
3.2.1运算器:执行算术和逻辑运算
算术逻辑单元(ALU) Arithmetic Logic Unit
运算器的核心部件,负责执行所有算术运算(加、减、乘、除)和逻辑运算(与、或、非、异或)。ALU是一个组合逻辑电路,根据控制信号对输入数据进行指定运算,并输出结果和状态标志。
累加寄存器(AC) Accumulator
为ALU提供工作区,存放一个操作数和运算结果。在执行运算时,累加器既作为数据源,也是运算结果的默认目的地。运算器中至少要有一个累加寄存器。
数据缓冲寄存器(DR) Data Register
作为CPU与内存、外部设备之间的数据传送中转站,暂时存放从内存读出的数据或准备写入内存的数据,起到速度缓冲的作用。
状态条件寄存器(PSW) Program Status Word (有争议,有归为控制器)
保存运算结果的状态标志,包括进位标志(C)、溢出标志(V)、零标志(Z)、符号标志(N)等。这些标志位被控制器读取,用于条件跳转等控制决策。
3.2.2控制器:解析指令、产生控制信号
程序计数器(PC) Program Counter
存放下一条要执行的指令的地址
指令寄存器(IR) Instruction Register
存放当前正在执行的指令。从内存中取出的指令先送入IR暂存,控制器对IR中的指令进行译码分析,确定要完成的操作类型和操作数位置。
指令译码器(ID) Instruction Decoder
对指令寄存器中的指令进行译码分析,识别操作码(做什么操作)和地址码(操作数在哪里)。译码结果决定了后续控制信号的生成方式。
控制单元(CU) Control Unit
控制器的核心部件,根据译码结果和时序信号,产生各种微操作控制信号,指挥运算器、存储器、输入输出设备按正确时序协调工作。
时序部件
提供时序控制信号指令中的操作码字段
3.2.3存储器
存储程序指令和数据
3.2.4输入设备
将外部信息转换为机器可识别格式
3.2.5输出设备
将处理结果转换为人类可感知形式
3.3总线系统:部件间的信息通道
五大部件之间通过系统总线连接,总线是传输信息的公共通道,分为三类:数据总线(传输数据)、地址总线(指定存储位置)、控制总线(传递控制信号)。
数据总线(Data Bus)
双向传输数据,宽度决定一次能传输的数据位数
地址总线(Address Bus)
单向传输,宽度决定CPU可寻址的内存空间大小
控制总线(Control Bus)
传输读写控制、中断请求、时钟信号等控制信息
总系的性能指标:
带宽(B/S)
位宽(bit)
工作频率(Hz)
3.4指令系统
指令系统定义:一台计算机所能执行的全部机器指令的集合。
指令的格式:一条指令通常由操作码和操作数两部分组成:
操作码:
指明要执行的操作(加、减、传送、跳转等)
MOV、ADD、JMP
操作数
指明参与操作的数据或数据所在位置
寄存器编号、内存地址、立即数
常见的指令格式按操作数个数分为:
四地址指令:
ADD R1, R2, R3,R4→ R1 = R2 + R3 R4存放下一条指令的地址三地址指令:
ADD R1, R2, R3→ R1 = R2 + R3 下条指令从PC中取二地址指令:
ADD R1, R2→ R1 = R1 + R2 R1既参加运算又存放结果一地址指令:
ADD R1→ 累加器 = 累加器 + R1零地址指令(栈式计算机):
ADD→ 弹出栈顶两数相加,结果压栈
指令分类:
数据传送指令
作用:在寄存器、内存、I/O 之间复制数据。
例子:
MOV、LOAD、STORE、PUSH、POP
算术运算指令
作用:执行二进制加、减、乘、除、取模等。
例子:
ADD、SUB、MUL、DIV与之前学的二进制算术运算直接对应,这些就是 CPU 中 ALU 干的事。
逻辑运算指令
作用:按位与、或、非、异或、移位等。
例子:
AND、OR、XOR、NOT、SHL、SHR
控制转移指令
作用:改变程序执行顺序(实现循环、条件判断、函数调用)。
例子:
JMP(无条件跳转)、JZ(结果为零则跳转)、CALL、RET
输入输出指令
作用:改变程序执行顺序(实现循环、条件判断、函数调用)。
例子:
JMP(无条件跳转)、JZ(结果为零则跳转)、CALL、RET
其他特殊指令
系统调用、特权指令、浮点运算指令等。
寻址方式
寻址方式 说明 示例(假设 ADD) 实际计算的操作数 立即寻址 操作数直接写在指令中 ADD R1, #5 5 寄存器寻址 操作数在某个寄存器中 ADD R1, R2 R2 的值 直接寻址 指令中给出内存地址 ADD R1, [1000] 内存地址 1000 处的值 寄存器间接寻址 寄存器存放内存地址, ADD R1,(R2) R2 的值作为地址去内存取数 间接寻址 指令中给出的地址里存放的是另一个地址 ADD R1, @R2 R2 的值作为地址去内存取数 指令如何找到操作数(或操作数的地址)?这就是寻址方式。同样一条
ADD指令,可以加立即数、寄存器、内存中的值等。立即寻址:操作数是指令的一部分,在取指令阶段已经读入指令寄存器,可直接使用。
寄存器寻址:操作数就在 CPU 的寄存器中,控制器直接选通寄存器输出到 ALU。
直接寻址:从指令中取出内存地址 → 发送地址到内存控制器 → 等待内存返回数据。
寄存器间接寻址:从寄存器中取出地址 → 发送地址到内存 → 读取数据。
间接寻址:第一次内存访问得到指针 → 第二次内存访问得到真正的操作数。
4.流水线
定义:流水线技术(Pipelining)是现代 CPU 实现高性能的核心手段之一。它的思想类似于工业装配线:将一条指令的执行过程分解为多个独立的阶段,每个阶段由专门的硬件处理,多个指令的不同阶段可以同时进行。
为什么需要流水线?
早期 CPU 采用单周期实现:每条指令完成全部操作(取指、译码、执行、写回)后,才取下一条指令。这导致:
硬件资源利用率低(大部分时间只有一部分电路在工作)。
主频提升困难(最长路径决定时钟周期)。
流水线通过并行重叠来提高吞吐量(单位时间内完成的指令数),而非缩短单条指令的执行时间。
流水线周期:
各流水段中耗时最长的那一段的执行时间。记为
Δt
流水线总时间公式:
假设共有 n 条指令,流水线深度为 k段,流水线周期为 Δt,则完成全部 n 条指令所需的总时间:
理论公式:T=(t1+t2+t3+...+tk)+(n-1)* Δt实践公式:T= k * Δt +(n-1)* Δt
流水线吞吐率:TP
TP = n / T(总指令条数除以总时间)流水线最大吞吐率:流水线周期的倒数
1/Δt
流水线面临的三大冒险(Hazard):
结构冒险(Structural Hazard)
硬件资源冲突,例如指令和数据共用同一存储器,导致取指和访存不能同时进行。
解决办法:
分离指令缓存和数据缓存(哈佛结构)。
或者引入“流水线停顿”(插入气泡)
数据冒险(Data Hazard)
下一条指令依赖上一条指令的计算结果,而结果尚未写回。
解决办法:
转发(Forwarding / Bypassing):将 ALU 计算结果直接旁路到下一指令的 ALU 输入端,无需等待写回。
流水线停顿(Stall):插入空操作(气泡),等待数据就绪(当转发无法解决时,如 Load-Use 情况)。
编译器调度:重新排列指令,插入无关指令相隔。
控制冒险(Control Hazard)
分支、跳转等指令改变 PC,流水线可能预取了错误方向的指令。
解决办法:
分支预测:静态(总是预测不跳/跳)或动态(两位饱和计数器、TAGE 等)。
延迟槽(早期 RISC):分支指令之后的指令总是执行(填入有用指令)。
提前计算分支条件:将分支决议提前到 ID 或 EX 阶段,减少预测错误惩罚。
5.多级存储结构
多级存储结构是计算机为了解决速度、容量、成本三者之间的矛盾而采用的一种层次化组织方式。它的核心思想是:
越靠近 CPU 的存储器速度越快、容量越小、成本越高;越远离 CPU 的存储器速度越慢、容量越大、成本越低。
通过将不同层次的存储器组合起来,系统可以在接近高速存储器的性能下,获得接近大容量存储器的空间。
为什么需要多级存储?
单一类型的存储器无法同时满足三个要求:
CPU 速度极快(纳秒级),若直接配大容量 DRAM,访问延迟太长,CPU 会频繁空等。
SRAM 速度可匹配 CPU,但成本高、集成度低,做不大。
硬盘/SSD 容量大、便宜,但速度慢(微秒甚至毫秒级)。
因此,采用金字塔式的多级结构,让每一级作为下一级的“缓存”,数据按需逐级复制和移动。
存储器自上而下,组成6个层次结构,依次变得更慢、访问频率更低、容量更大、每字节的造价更便宜
寄存器 register
位于 CPU 内部,指令直接访问。
数量极少(如 32 个通用寄存器),但速度最快。
编译器负责分配寄存器来存放频繁使用的变量。
高速缓存 cache
利用程序局部性原理(时间局部性、空间局部性)自动将主存中可能被频繁访问的数据块复制到缓存。
映射方式:直接映射、组相联、全相联。
替换算法:LRU、LFU、随机、FIFO。
写策略:写直达(Write-Through)、写回(Write-Back)。
多级缓存:L1 分为指令缓存(I-Cache)和数据缓存(D-Cache),L2/L3 统一。
主存储器
采用 DRAM,需要定期刷新。
通过内存控制器与 CPU 通信,地址空间按字节编址。
虚拟内存技术:将部分磁盘空间模拟为内存(交换区),允许运行超过物理内存的进程。
外部存储器
SSD:无机械部件,随机读写快,用于操作系统和常用程序。
HDD:机械寻道,顺序读写快,适合大容量冷数据存储。
远程二级存储器
通过网络协议(如 NFS、SMB、iSCSI)访问,延迟最高,但提供近乎无限的容量和数据共享。
以 CPU 读一个 32 位整数为例(假设 L1 未命中):
CPU 发出虚拟地址 → MMU 转换为物理地址。
硬件先检查 L1 缓存:若命中(~90%+概率),数据在约 1ns 内返回。
若 L1 未命中,检查 L2 缓存(延迟 ~10 ns),并同时将数据块提升到 L1。
若 L2 未命中,检查 L3 缓存(延迟 ~40 ns)。
若 L3 未命中,发起 主存访问(延迟 ~100 ns),并读取一个缓存行(通常 64 字节)填入 L3、L2、L1。
若发生缺页(数据不在主存中),触发操作系统将页面从磁盘读入内存(毫秒级延迟,包含 3~6 个数量级的性能悬崖)
Cache映像方式
直接映像
每个主存块只能映射到唯一的Cache行。实现简单、速度快,但容易发生冲突——不同主存块争抢同一Cache行。
全相联映象
主存块可放入任意Cache行。命中率最高、无冲突,但需要遍历所有Cache行进行Tag比较,硬件复杂度高。
组相联映像
Cache分组,主存块映射到特定组,组内任意行可存放。折中方案——既减少冲突,又控制硬件复杂度。
6.I/O控制方式
I/O控制方式的演进遵循一个简单逻辑:让专业的人做专业的事。CPU擅长计算,I/O设备擅长数据传输,DMA控制器和I/O通道就是"专业数据传输员"。从程序查询到通道控制,CPU的干预程度从"全程陪同"降到了"发号施令",这正是计算机系统追求高效率的缩影。
6.1程序查询方式(轮询)
CPU发送I/O指令后,不断循环查询设备状态寄存器,直到设备就绪。这种方式实现简单,但CPU利用率极低——设备越慢,CPU浪费的时间越多。
6.2中断驱动方式
设备完成数据准备后主动向CPU发送中断信号,CPU只在收到中断时才处理I/O。这样CPU可以在等待期间执行其他任务,但每个字的数据传输仍需CPU介入。
6.3DMA方式(直接存储器访问)
DMA控制器接管总线,直接在设备和内存之间传输整块数据,仅在传输开始和结束时需要CPU干预。数据块越大,效率提升越明显。
6.4通道控制方式(IOP)
I/O通道是专用的I/O处理器,执行内存中的通道程序来管理多设备。CPU只需发送一条I/O指令,通道就能独立完成一组复杂的I/O操作,实现CPU、通道、设备三者并行。
7.可靠性
可靠性是计算机系统在规定的条件下、规定的时间内完成规定功能的能力。它衡量系统在面对硬件故障、软件错误、网络中断等异常情况时,仍能保持服务连续性的能力。高可靠性系统通过冗余设计、故障检测与自动恢复机制,将停机时间降至最低。
核心指标
失效率(Failure Rate) λ = 故障次数 / 总运行时间
平均故障间隔时间 MTBF = 1/λ
平均修复时间 MTTR
系统可用性=MTBF / (MTBF + MTTR)
8.校验码
8.1概述
检验码(Check Code)是数字通信与存储系统中通过添加冗余信息来检测或纠正数据传输错误的技术。
错误产生原因:
由于硬件噪声、信号衰减等因素,二进制数据可能发生位翻转(0变1或1变0)
核心思想:
用冗余度换取可靠性——在原始数据后附加校验位,使接收端能够发现甚至修复传输过程中产生的错误。
检验码的本质是建立数据位与校验位之间的数学关系。
常用校验码:
奇偶校验码
海明码
循环冗余校验码
8.2奇偶校验码(Parity Check)
原理:在原数据位后附加一个校验位(奇偶位),使得整个码字中“1”的个数为奇数(奇校验)或偶数(偶校验)。
示例(偶校验):
数据:
1011(已有3个1)需要总1的个数为偶数 → 补1个1 → 校验位=1
最终码字:
10111接收方检查:若收到
10111,1的个数为4(偶数),认为正确;若为10101(1的个数=3,奇数),则发现错误。
优点
实现简单,仅需1位冗余
硬件开销极小
常用于串行通信(如UART)或内存的简单校验(如早期RAM的ECC只是奇偶)
缺点
只能检测奇数个错误(如1位、3位、5位...),无法检测偶数个错误(如:当有两位出错时,校验正常)
不能定位错误位置,也无法纠正。
8.3海明码(Hamming Code)
原理:在数据位之间插入多个校验位,每个校验位覆盖不同的数据位组合。错误发生时,通过校验位的状态(错误定位字)直接指出错误位置,从而纠正单个位错误。
基本参数:对于 k 位数据,需要 r 位校验位,满足:
2^r ≥ k+r+1校验位位置:放在 2^0,2^1,2^2,… 位上(即第1、2、4、8、…位,位编号从1开始)。
校验规则:第 i个校验位(i=2^j)覆盖所有位号在二进制表示中第 j位为1的位(从0开始计)。
如: 第一个校验位 是第 2^0 , 检验总排序所有第0位为1的位,
海明码的编码步骤(以(7,4)为例)
4位数据位,则最少需要3位校验位,才能满足
2^r>K+r检验位位置在分别在
2^0,2^1,2^2,即第 1、2、4位上4数据位则分别在第3、5、6、7位上
排序
P1、P2、D3、P4、D5、D6、D7P1校验第0位为1的位,即
P1、D3、D5、D7P2校验第1位为1的位,即
P2、D3、D6、D7P4校验第2位为1的位,即
P4、D5、D6、D7计算校验位的值(通常采用偶校验),若数据1010:D3=1,D5=0,D6=1,D7=0,则:
P1=D3⊕D5⊕D7=1⊕0⊕0=1(所校验的数据位1的个数为奇数,为保证偶数个1,所以取1)
P2=D3⊕D6⊕D7=1⊕1⊕0=0
P4=D5⊕D6⊕D7=0⊕1⊕0=1
最终码字(位1~7):P1=1,P2=0,D3=1,P4=1,D5=0,D6=1,D7=0→ 1 0 1 1 0 1 0
数据1010加入海明码后变为1011010
纠错过程,接收方收到码字 r1r2r3r4r5r6r7后,计算校正子
S1=r1⊕r3⊕r5⊕r7=1⊕1⊕0⊕0=0
S2=r2⊕r3⊕r6⊕r7=0⊕1⊕1⊕0=0
S4=r4⊕r5⊕r6⊕r7=1⊕0⊕1⊕0=0
若 二进制数 S4S2S1=000,则无错误。
否则 二进制数 S4S2S1 表示出错的编号
假设在发送1011010 时,传输过程中第5位发生翻转 1011110
S1=r1⊕r3⊕r5⊕r7=1⊕1⊕1⊕0=1
S2=r2⊕r3⊕r6⊕r7=0⊕1⊕1⊕0=0
S4=r4⊕r5⊕r6⊕r7=1⊕1⊕1⊕0=1
二进制数S4S2S1 = 101 即第五位出错
8.4循环冗余校验(CRC, Cyclic Redundancy Check)
原理:
CRC 的核心是 多项式模2除法(也称多项式算术)。
将一串二进制数据看作一个多项式的系数,例如
1101对应M(x)=1⋅x^3+1⋅x^2+0⋅x+1=x^3+x^2+1。发送方和接收方约定一个生成多项式 G(x),其最高次项为
x^r(例如1011对应x^3+x+1,r=3)。发送方在数据末尾附加 r 位校验码,使整个码字多项式 T(x)能被 G(x) 整除。
接收方用 G(x)除以收到的码字,余数为0表示无错。
关键公式:CRC校验码=(M(x)⋅x^r)modG(x)
即:先把原始数据左移 r 位(末尾补 r 个0),再除以 G(x)取余数。
例:使用长除法手工计算,以数据
1101,生成多项式1011(r=3)为例:左移 3 位:
1101→1101000(相当于乘以 x^3)模2除法(用异或代替减法,不借位)
位操作过程(初始被除数 = 1101000): 1. 取前4位 1101,除数 1011 → 1101 XOR 1011 = 0110 → 余数 110(去掉前导0) 2. 拉下一位 0 → 1100,除数 1011 → 1100 XOR 1011 = 0111 → 余数 111 3. 拉下一位 0 → 1110,除数 1011 → 1110 XOR 1011 = 0101 → 余数 101 4. 拉下一位 0 → 1010,除数 1011 → 1010 XOR 1011 = 0001 → 余数 001 最终余数 = 001。发送码字 = 原始数据 1101 + 余数 001 = 1101001。 接收方用 1011 去除 1101001,余数应为 000
8.5校验码对比
| 类型 | 检错能力 | 纠错能力 | 冗余开销 | 复杂度 | 典型应用 |
| 奇偶校验 | 只能检测奇数个位错误 | 无 | 最低 (每组1位) | 极简单 | UART、简单内存 |
| CRC | 强(可检测突发错误) | 无(通常) | 低 (16/32位) | 中等 | 网络、存储 |
| 海明码 | 可检测1~2位错(扩展) | 可纠正1位错 | 中等 (log N + 1位) | 较高 | ECC内存、通信 |
