计算机组成原理前三章核心精讲:从数据表示到Cache存储系统

发布时间:2026/10/13 19:36:05
计算机组成原理前三章核心精讲:从数据表示到Cache存储系统 说实话很多人刚开始学《计算机组成原理》的时候都会被原理两个字吓住。尤其是前几章这个概念还没消化那个公式又冒出来了一节课下来只觉得头晕。我当年学这几章也有同感但后来真正把它啃完再回头看一到三章才发现这几章其实是整门课的命脉也是性价比最高的一部分。它讲清楚了三个问题一台计算机到底是怎么跑起来的、数字在机器里是以什么样的形态参与运算的、以及数据是被一套什么样的存储体系管起来的。这篇文章不打算给你复述教科书。我主要结合自己学习和做题的体会把一到三章的核心内容拆开揉碎讲清楚那些公式和概念背后的逻辑顺便把大家容易踩的坑、考试和复习时真正要注意的点都交代一遍。无论你是正在上课的本科生、准备考研的二战党还是工作后想回来补基础的开发者只要能把这三章吃透后面的控制器、指令系统学起来会轻松很多。1. 计算机系统总貌第一章到底在讲什么1.1 系统的层次结构别小看这张金字塔第一章的开篇通常都会给一张计算机系统的层次结构图从最底层的微程序机器层往上到传统机器层、操作系统层、汇编语言层再到高级语言层。很多同学觉得这只是一个概念框架背一背就过去了。但我的看法是这张图是理解整台机器工作本质的地图什么时候都不要丢掉它。为什么这么说因为程序跑起来的过程说白了就是一层一层翻译或解释的过程。高级语言写出来的代码经过编译、汇编、链接最终变成机器能够识别的指令。而这些指令在传统机器层执行时又由微程序或硬布线控制部件逐条解释。如果你没有这个层次的意识碰到后面指令周期微操作这类内容时会觉得特别散不知道该把这些知识挂在哪里。反过来脑子里有这张图之后遇到任何问题你都能先问一句这一层是处在哪个位置是硬件在做还是操作系统在做这能帮你快速定位问题。另外我在复习时还发现层次结构的思想不仅用来描述计算机几乎贯穿整本教材。比如第二章讲的数据表示本质就是解决高级语言里的整数和小数如何落到机器层第三章讲的Cache和主存本质就是操作系统层和硬件层之间做数据搬运的配合。所以学第一章时不要急着往后赶多花点时间把层次关系看明白后面会顺很多。1.2 冯·诺依曼结构与一条指令的一生说到计算机的基本结构必然绕不开存储程序的概念。程序在执行前先装入主存机器从主存中逐条取出指令分析这条指令要做什么然后取来操作数并执行最后把结果写回。这段话几乎每本教材都有但很多人忽略了一个关键的视角一条指令的一生其实就对应了一个完整的时空过程。我习惯把这个过程拆成四个环节取指、译码、执行、回写。取指就是根据程序计数器给出地址到主存把指令拿回来译码是弄清楚这条指令的类别和操作数位置执行是让运算器等部件真正干活回写则是把计算结果保存到目标寄存器或内存单元。从这个角度看冯·诺依曼结构最大的特点是指令和数据同样存放在存储器中——这意味着取指阶段拿到的是一串二进制执行阶段处理的又是另一串二进制只不过它们的语义不同。而我们后面学的数据通路、控制器时序全都是围绕这四个环节展开的。学到这里时我建议自己动手画一条加法指令的完整流程比如ADD R1, R2, R3画出每一步需要哪些部件参与、哪些信号打开、哪些数据在总线上流动。画完这个图你会对计算机如何自动工作有一个非常直观的感觉而不是等到学CPU设计时才反过来补课。1.3 性能指标别只看主频第一章还有一个很现实的话题就是评价一台计算机的性能。很多同学看参数时第一眼就是看主频觉得3.5GHz一定比2.0GHz快。实际上这是一个大坑。课程里给了一组最核心的公式CPU执行时间 指令条数 × 平均每条指令时钟周期数CPI × 时钟周期。如果是相同架构、相同指令集主频高确实有优势但一旦架构不同主频高并不等于执行快因为处理器每拍能做的有效工作差别很大。讲到后面你会明白流水线、超标量、多发射这些技术都是在压榨每一拍的价值单纯拼频率早就不是主流方向了。这里有两个常量要分清楚MIPS每秒执行百万条指令和MFLOPS每秒执行百万次浮点运算。MIPS看起来直观但它有个明显缺陷——不同指令集里一条指令的含金量完全不同。比如一个精简指令集处理器要执行五条指令干完的事在一个复杂指令集处理器里可能一条指令就搞定了这时MIPS数字低不代表慢。所以比较性能时最好用程序的实际运行时间或者针对特定负载的指标尽量不要拿某单一指标去下结论。做题时也容易混淆CPI和MIPS的换算。MIPS实际上等于主频除以CPI再除以10^6这个公式里主频用的是Hz算出来才是每秒百万条指令。我当年复习时就因为单位换算栽过一次建议你们遇到这种题先统一单位再套公式。2. 第二章的数据表示从进制转换到补码的本质2.1 进制转换的基本功手速和准确率怎么练第二章一上来就是二进制、八进制、十六进制的转换。很多人觉得这是纯体力活没什么好学的但你做后面的补码、浮点运算时几乎每一步都依赖进制转换的熟练度。如果你现在还经常把二进制和十六进制对不上号后面的效率会大打折扣。整数部分用短除法小数部分用乘法取整这些方法教材上都有。我想分享的是另一个层面的技巧进制转换的核心是权值意识。每一位数字的价值等于该位数字乘以该位对应的权比如二进制从右往左的权分别是1、2、4、8……十六进制则是1、16、256……只要有了权值这个概念任何进制之间的转换都不需要死记算法而是可以推导出来。练习时我建议给自己定一个目标十以内的数二进制和十六进制能做到条件反射100以内的数能做到5秒内换算出来。手速练出来之后做后面IEEE 754浮点数转换时会感到非常轻松因为整个尾数和阶码的拼接本质上就是一组十六进制到二进制的映射。2.2 原码、反码、补码、移码四个编码背后的设计逻辑这一章的重头戏无疑是定点数的四种机器码表示。很多同学靠背表格来区分它们的正负数形式但背来背去还是容易混。我的经验是把每个编码当作一个有明确设计目标的工具来理解。先看原码它是人类最直观的表示方式符号位加绝对值。但原码做加减法非常麻烦先要比较两个数的符号再决定是做加法还是减法符号不同的情况还要比较数值大小。为了简化硬件设计者想出的办法就是用补码。补码的核心思想是把减法变成加法让符号位也参加运算。为什么能实现这个效果因为计算机的字长是有限的当一个数加上它的负数正好溢出变成一个模的倍数结果就是0对某个模取余。所以在模运算的意义下一个负数可以用它的补数来表示这就是补码的由来。反码在其中扮演了过度角色负数的反码是原码按位取反补码则是反码加1。所以补码的求法和它作为负数等价表示的性质是同一枚硬币的两面。理解了这一点你就不需要死记取反加一而是知道为什么有这一步。移码则主要用于浮点数的阶码表示。它的设计意图更纯粹让阶码大小的比较变得容易因为移码直接把它变成无符号数数值越大真值越大。四者的关系我建议画一个数轴对照图把零、边界值标清楚尤其是补码的不对称性——负数的范围比正数多1这在取反加一时涉及边界问题时特别容易出错。2.3 定点加减运算与溢出判断的硬核细节补码定点加减法看起来很简单补码加法就是按二进制加法直接加符号位自然参与补码减法则是把减数取负之后做加法。但这里有个隐藏考点——溢出怎么判断。我经常看到有同学算出一个离谱结果后不知道自己算错了其实是因为忽略了溢出。教材里给了两种常用判断方法。第一种是单符号位判断如果两个同号数相加结果符号与它们不同就说明溢出了。第二种是双符号位判断也就是采用变形补码用两个符号位表示正负比如00代表正、11代表负。正常运算结果两个符号位应保持一致如果得到01说明正溢出得到10说明负溢出。这个方法的优点是在硬件上通过异或逻辑就能判断非常直接。做题时我有一个习惯算完结果之后立刻把参与运算的数还原成十进制用心算核对一遍。这个习惯救了我很多次因为补码运算中间容易看错位而十进制验算几乎不会错。比如两个负数补码相加结果如果看起来变成了正数那必然不是算错了就是溢出了绝对不会有什么中间状态存在。另一个常见考点是符号扩展。把一个短字长的补码扩展成更长的字长正数在高位补0负数在高位补1。这个操作可不只是为了做题实际硬件在做类型提升时干的就是这件事。如果你把负数补0扩展了数值就彻底变了这在后面学指令系统时还会碰到。2.4 IEEE 754浮点数阶码、尾数与那些不对劲的数定点数的表示范围有限远远满足不了科学计算的需求所以浮点数被设计成类似科学计数法的形式。IEEE 754标准的单精度格式是32位1位符号、8位阶码、23位尾数。这里有两个极其容易出错的地方。一是阶码采用移码表示单精度的偏置值是127。也就是说当你把阶码的二进制值解读为无符号整数后要减去127才是真正的指数大小。这个偏置的存在就是为了让阶码能够用无符号数的大小关系来比较指数大小简化硬件判断。我一直建议大家在纸上把偏置常数标在阶码旁边不然一不留神就会把127当成浮点数的一次方来处理。二是规格化数的尾数有一个隐含的1。因为规格化之后二进制小数部分最高位必然是1开头所以这个1不存储只存小数点后面的23位。因此实际尾数精度是24位二进制有效数字。解码时要在尾数前面补上那个隐藏的1然后按照权位还原十进制值。以0和无穷大为界浮点数还定义了阶码全为0和全为1的特殊情况很多人做题时忽略了这些边界导致表示不出来的数被当成普通数处理。我还建议拿0.1这个十进制小数走一遍完整的转换流程。你会发现0.1用二进制表示是无限循环小数只能近似存储。这就是为什么计算机里0.1加0.2不等于0.3的根源。理解这个原理之后你在写程序时就会对浮点等值判断格外谨慎这就是组成原理指导工程实践的典型例子。3. 第三章存储系统数据的栖身之所3.1 存储层次结构为什么越快的存储器越贵第三章的主题是存储系统其实整个存储系统设计追求的目标可以概括为一句话让CPU在尽量短的时间内拿到它想要的数据同时让整个系统的成本不要失控。寄存器、Cache、主存、辅存逐级变大变便宜、逐级变慢这一层级关系的存在根本原因是局部性原理。局部性原理包含两个维度。时间局部性是指如果一个数据被访问了在不久的未来它很可能再次被访问典型场景就是循环体中的变量和指令。空间局部性则是指如果一个地址被访问那么它邻近的地址很快也会被访问典型场景就是顺序执行的指令和数组遍历。正是因为这些访问不平均我们才敢用小而快的Cache去缓存那些频繁使用的数据用大而慢的主存放下暂时不用的部分让整体性能接近高速端成本接近低速端。学习这部分时我建议把存储层次想象成一个带缓存机制的文件系统CPU是那个需要频繁读资料的人Cache是桌面上的文件夹主存是旁边的大书柜辅存是仓库。你肯定优先从桌面文件夹里拿资料因为最快找不到才去书柜翻。这个类比虽然粗糙但足够帮你建立命中和不命中的直觉。3.2 主存里的DRAM与SRAM刷新为什么这么重要主存储器一般就是我们说的内存条它由DRAM芯片组成。DRAM的基本存储单位是一个电容加一个晶体管电容里存电荷表示1没有电荷表示0。电容会漏电所以需要定期刷新否则数据就丢了。这是DRAM容量大但速度相对慢、还需要刷新电路的核心原因。与之相对的是SRAM它用触发器电路来保存状态不需要刷新速度也快得多但电路复杂、集成度低所以成本高通常用在Cache里。我当年理解不了为什么SRAM贵后来学IC设计的相关内容时才明白一个SRAM存储单元要用六只晶体管而DRAM只要一只晶体管加一个电容差距在芯片面积上非常直观。还有一个工程细节容易被忽略——地址复用。DRAM芯片为了减少引脚数量把地址分成行地址和列地址分两次送入先传行地址再传列地址。这个特性直接影响存储器的读写周期也是课程里计算芯片组成、设计主存时绕不开的点。比如设计一个主存模块需要几片DRAM、怎样进行位扩展和字扩展这些题目表面是在考芯片拼接实际上考的还是你对地址信号时序的理解。我建议自己动手画一张地址线、片选线、读写控制线的连接图画一遍比看十遍都管用。3.3 Cache映射方式与地址拆分一道题吃透Cache在存储系统里是最讲究性价比的环节映射方式决定了主存块能放到Cache的哪些位置。直接映射、全相联映射和组相联映射三者的自由度和硬件复杂度依次递增。直接映射是每个主存块只能放到Cache中唯一的一个位置所以地址被拆成三部分块内地址、Cache索引、标记。全相联映射则完全没有索引的限制任何主存块可以放在任何Cache块中地址中只保留块内地址和主存块标记硬件需要对所有Cache块并行比较。组相联映射介于两者之间把Cache分成若干组主存块可以映射到组内任意一个块位置地址结构通常是块内地址、组索引、标记三部分。我强烈建议你拿一道具体题目完整地算一遍。比如一个主存容量为64KB、块大小为16B、Cache容量为4KB、按直接映射方式组织那么主存地址应该是多少位块内地址需要几位Cache一共有多少块索引需要几位这样算下来你就能看到主存地址的位分配是如何由Cache容量和块大小共同决定的。起初容易漏掉的地方是组相联的组和块的关系组数等于Cache块数除以每组块数索引位取自该除法结果而不是直接取自Cache总块数。还有一个细节是Cache总容量的计算。很多教材喜欢问Cache的容量这时候容易把数据容量和总容量搞混。总容量除了数据位还要加上有效位和标记位。有效位用于标明这个Cache行是否已有有效数据标记位用于对应当前存储的是哪个主存块。我做题时总是先把哪些位属于数据、哪些位属于辅助信息列出来再分别计算这样不容易丢位。3.4 替换算法与平均访问时间的计算这套逻辑不能乱Cache满了之后要替换旧块最常考的替换算法是LRU和FIFO。LRU的全称是最近最少使用它选择最长时间没有被访问的块进行替换。FIFO则是先进先出按进入Cache的顺序来。还有一个随机替换实现最简单但命中率不稳定。考试时通常会给你一个访问序列和映射方式让你按LRU或FIFO逐个更新Cache状态最后统计命中次数。这里我有个经验画表格时横轴是访问次序纵轴是Cache块号每次访问都按顺序标出当前Cache状态然后逐拍更新千万不要靠脑补推演。画表虽然慢一点但准确率极高遇到复杂的组相联替换也不容易乱。平均访问时间的公式也是必须滚瓜烂熟的平均访问时间 命中率 × Cache访问时间 未命中率 × 主存访问时间。严格一点的教材会把未命中时的访问时间细分为Cache访问时间 主存访问时间因为Cache不命中后先要判断取回主存数据再填充Cache并返回给CPU。不同教材的处理方式略有差异做题前先看清楚题干给的是额外开销还是完整的未命中访问时间。一个具体的例子往往能说明问题假设Cache访问时间是1个时钟周期主存访问时间是50个时钟周期命中率是90%按公式算平均访问时间大约为1×0.9 (150)×0.1 5.4个周期。如果命中率提升到98%平均访问时间降到1×0.98 51×0.02 3.92个周期。从9成到九成八的命中率提升平均性能提升了超过25%这就是为什么Cache设计拼命追求高命中率以及局部性优化为什么如此重要。4. 学习避坑与复习经验这些坑我替你踩过了4.1 一到三章怎么串起来学别把它们当成孤岛很多同学学习时是章章独立的学完第二章就把第一章忘了学完第三章又忘了第二章。实际上这三章之间有一条非常清晰的主线一个程序要运行需要先把指令和数据准备好这就涉及第三章的存储系统数据在机器里以什么形式表示这就是第二章讲的数制与编码指令如何被取出来并按流程执行这就是第一章讲的基本结构。后面的指令系统、CPU设计无非是把这条主线画得更细。所以我把这三章称为前置地基章。复习时我建议按数据路径去记忆数据从辅存到主存再到Cache最终进入寄存器参与ALU运算中间每一步都牵扯存储层次和表示形式。你甚至可以自问自答一个C语言里的int变量从定义到参与一次加法它在存储体系里经历了什么这个答案串起来就是这三章最重要的内容。4.2 做题时最容易翻车的地方结合我自己的经历我整理了一份高频易错点清单。补码取负时忘了取反加一的加一环节往往是第一步就把数弄错了。符号位扩展时正数和负数规则完全不同考试时会故意设计一个需要扩展的减法。移位运算和乘除法的等价关系只在补码表示下才成立算术右移要在高位补符号位逻辑右移高位补0这两者的区别特别容易在综合题里出错。浮点数规格化时尾数的隐藏1没有补上或者阶码的偏置常数没有正确加减都会导致最终数值差得很远。Cache地址拆分时索引位数、标记位位数和块内地址位数的总和必须等于主存地址总位数很多同学算完总和多一位或少一位还不自知就是因为没有做这个核对。最后还有性能指标换算时单位不一致比如MHz和GHz没有统一就直接代入公式算出来会差三个数量级。我建议你把这张清单抄在笔记的第一页每次做题前扫一眼能帮你绕开大约七成的基础错误。4.3 关于复习与备考的一点看法如果你是为了应对考试我想提醒你的是组成原理这门课光靠看和背是不够的动手算才是唯一的捷径。教材课后题里那些进制转换、补码加减、浮点数编码、Cache映射计算每一类都必须独立完整地做上几遍。尤其是浮点数的转换题第一次做容易卡在异常值判断上做几道后发现规律就顺手了。再一个建议是把每一个公式都从头推导一遍不要直接背结论。比如补码的补码等于原码、平均访问时间公式、MIPS与CPI的关系这些如果你能自己推出来遇到变形题也不会慌。推导的过程本身还帮你记住了很多容易被忽略的边界条件比如偏置常数为什么是127而不是128。有些同学喜欢看视频课这是一种很好的起步方式但看完一定要自己再走一遍例题。看懂了和会做了之间的距离在这门课上体现得特别明显。4.4 组原内容对实际开发的隐形帮助学完前三章后你在日常开发里会突然冒出一些不一样的感觉。比如你写C语言时把循环变量从int改成short表面上是省内存但如果你知道符号扩展和位数表示的细节就能更准确地判断这一改会不会引入精度或溢出问题。写多线程程序时你会意识到Cache和内存之间的一致性是个大问题多核CPU访问同一个缓存行时可能会产生严重的性能抖动这就是经典的多线程伪共享问题。浮点数运算的误差问题更是无处不在只要你对IEEE 754有概念就不会写出直接拿浮点数相等的判断逻辑也不会惊讶于0.1加0.2不等于0.3。这些看起来是编程层面的问题根子都在组成原理的头三章里。学得深入的人看到的计算机是一个分层合作、充满权衡的系统而不是一堆黑盒。回到我自己我对前三章最大的感受是它们像一串钥匙打开了计算机硬件世界的门。初学时觉得繁琐的细节在实际做题和回顾之后都变成了理解更深层内容的台阶。如果你现在正卡在某一步我的建议其实很简单——找一张纸一支笔把那个问题的全过程从头到尾画一遍、算一遍。多数时候卡住你的不是难度而是那个还没有被亲手走通的环节。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询