生活不可能像你想象得那么好,但也不会像你想象得那么糟。
我觉得人的脆弱和坚强都超乎自己的想象。
有时,我可能脆弱得一句话就泪流满面;有时,也发现自己咬着牙走了很长的路
前言知识
机器字长:计算机一次整数运算所能处理的二进制位数
.exe文件就是用机器语言描述的程序
1.1 计算机的发展
计算机系统=软件+硬件
软件分为系统软件和应用软件
系统软件:用来管理整个计算机系统(eg:操作系统,数据库管理系统,标准程序库,网络软件,语言处理程序,服务程序)
应用软件:按任务需要编制成的各种程序(eg:抖音,王者荣耀,迅雷等)
硬件的发展
第一台电子数字计算机:ENIAC(手动接线来控制计算) 1946 逻辑元件:电子管
第二代:逻辑元件:晶体管
第三代:逻辑元件:中小规模集成电路,将元件集成在基片上
第四代:逻辑元件:大规模,超大规模集成电路,开始出现“微处理器”,微型计算机 ,个人计算机pc 萌芽 苹果A13制造工艺:7nm 也就是每一个逻辑元件不超过七纳米的工艺水平,微处理器8080机器字长8位,微处理器8086机器字长16位
摩尔定律:揭示了信息技术进步的速度,集成电路上可容纳的晶体管数目,约每隔18个月便会增加一倍,整体性能也将提升一倍
计算机硬件的基本组成:早期冯诺依曼机的结构,现代计算机的结构
1.2 计算机硬件的基本组成
早期冯诺依曼机
“存储程序”的概念是指将指令以二进制代码的形式事先输入计算机的主存储器,然后按其在存储器中的首地址执行程序的第一个指令,以后就按该程序的规定顺序执行其他指令,直到程序执行结束,就不需要每一步都进行手工连接的操作,进而来提高速度
输入设备:将信息转换成机器能识别的形式
存储器:存放数据和程序
运算器:算术运算逻辑运算
输出设备:将结果转换成人们熟悉的形式
控制器:指挥程序运行,控制器从存储器中读取一个指令的数据流,这样他才会指挥运算器
在计算机系统中:软件和硬件在逻辑上是等效的,意思也就是同一个功能可以使用软件实现,但是也可以使用硬件实现,eg:对于乘法运算,可以设计一个专门的硬件电路实现乘法运算也可以用软件的方式,执行多次加法运算来实现
冯诺依曼计算机的特点:1:计算机由五大部件组成,2:指令和数据以同等地位存于存储器,可按地址寻访,3:指令和数据用二进制表示 4:指令由操作码和地址码组成 5 存储程序,6 以运算器为中心,输入/输出设备与寄存器之间的数据传送通过运算器完成
现代计算机的结构
以存储器为中心, 输入输出设备直接从存储器存取数据,这样就可以解放更多的运算器的时间,由于运算器以及控制器的关系十分紧密,所以在大规模集成电路出现之后,这两个东西通常被集成于同一个芯片上,这个芯片通常也就叫cpu,cpu通过控制线控制运算器,你接下来要执行的是什么操作,另外控制器也会控制主存储器的一个读写,以及输入输出设备的启动与停止,主存储器也会与cpu进行数据的交换,第一种就是参与运算的数据会放在运算器中,指令会放在控制器中,由控制器来进行解析,并发出相应的控制信号,主存储器和cpu统称为主机,主存和辅存统称为存储器,这里要注意主存(运行内存)属于主机,而辅存(机身存储)属于i/o设备
主存储器的基本组成
主存储器有三个部分:存储体,MAR,MDR
主存储器中用于存储数据的东西叫做存储体,存储体是由一系列的存储元件组成的,可以存放二进制的零或者一
MAR: 存储地址寄存器
MDR:存储数据寄存器
cpu会将它想读的数据的地址写到MAR中,主存储器就可以根据MAR中的地址并把数据先写到MDR中去,最后cpu就可以通过数据线路从MDR中取走数据,写也是同样的操作 cpu会将要写的数据的地址放在MAR中,将数据存放在MDR中,最后cpu会通过控制总线告诉主存储器,这次要执行的是写操作 主存储器可根据这三个信息便可写入数据
存储单元:每个存储单元存放一串二进制代码,存储字:存储单元中二进制代码的组合,存储字长:存储单元中二进制代码的位数,存储元:既存储二进制的电子元件,每个存储元可存1bit
运算器的基本组成
运算器:用于实现算术运算,逻辑运算
ACC:累加器,用于存放操作数,或者运算结果
MQ;乘商寄存器,在乘,除运算时,用于存放操作数或者运算结果
x:通用 的操作数寄存器,用于存放操作数
ALU(核心单元):算术逻辑单元,通过内部复杂的电路实现算数运算,逻辑运算
控制器的基本组成
CU:(核心单元)控制单元,分析指令,给出控制信号
IR:指令寄存器,存放当前执行的指令
PC:程序计数器,存放下一条指令地址,有自动加1功能
完成一条指令:取指令PC 分析指令IR 执行指令CU
计算机系统的层次结构
下层是上层的基础,上层是下层的扩展
编译程序:将高级语言编写的源程序全部语句一次全部翻译成机器语言程序,而后再执行机器语言程序(只需翻译一次,生成.exe文件,下次直接点击exe文件即可)
解释程序:将源程序的一条语句翻译成对应机器语言的语句,并立即执行,紧接着再翻译下一句(每一次执行都要翻译)
1.3 计算机的性能指标
存储器的性能指标
MAR位数反映存储单元的个数(最多支持多少个)
MDR位数=存储字长=每个存储单元的大小
总容量=存储单元个数存储字长(bit) 1Byte=8bit
cpu主频(时钟频率):cpu内数字脉冲信号震荡的频率 等于时钟周期分之一
cpi:执行一条指令所需要的时钟周期数(不同的指令,cpi不同,甚至相同的指令,cpi也可能有变化)
执行一条指令的耗时=cpicpu 时钟周期
IPS每秒执行多少条指令,IPS=主频/平均CPI
系统整体的性能指标
数据通路带宽:数据总线一次所能并行传送信息的位数(各硬件部件通过数据总线传输数据)
吞吐量:指系统再单位时间内处理请求的数量 系统的吞吐量主要取决于主存的存取周期
响应时间:指用户向计算机发送一个请求,到系统对该请求做出响应并获得它所需要的结果的等待时间
基准程序是用来测量计算机处理速度的一种实用程序 也就是跑分软件
2.1.1 进位计数制
任意进制转化十进制
二进制转化为八进制
三个二进制数正好可以表示八种不同的状态
以小数点开始左右3位为一组,每组转化为对应的八进制符号(高位整数补零,地位小数补零)
二进制转化为十六进制
四个二进制数正好可以表示十六种不同的状态
以小数点开始左右4位为一组,每组转化为对应的16进制符号
八进制转化二进制
十六进制转化为二进制
进制的常见书写方式
二进制以B结尾,八进制以O开头,十六进制以H结尾或者以0x开头,十进制以D结尾
十进制转化为任意进制
方法一
(除基取余法整数部分):任意一个整数都可以写成整数X(R的一次方,二次方,一直到n-1次方,所以是可以整除的)部分加上余数K0(0~R)部分 ,所以我们除以R之后得到余数K0便是R的零次方上的数值,再用得到的商再除以R得到的便是K1(先取得的余是整数的低位)
(乘基取整法小数部分):核心思想也是一样 想办法把K-1算出来,这里发现乘上一个R便可直观的得到K-1的值 ,得到的结果再乘R得到的便是K-2的值(先取得的整是小数的高位)
方法二(拼凑法)
若是给你的十进制数不是特别大的话,可能使用这些拼拼凑凑的方法可能要快一些,假如要将十进制转化成八进制,完全可以先转化成二进制,然后二进制再三位一组转化为八进制
小结回顾
2.1.2 BCD码
BCD:用二进制编码的十进制
8421码
通过上述我们知道要想表示0~9这十个数,必须最少需要4bit,而4bit则可以表示16个值 ,这样也就会有6个yong余,8421码的提出便是为了快速转换
8421码的相加:若是两个数对应的8421码相加的结果不在映射表中,也就是落到了10~15这个区间这个时候我们再加上6 这样就一定会向高位进一个1,而低位所留下的部分又正好是我们个位所留下的部分
余3码
也就是在8421码的基础上加上一个0011得到不同的映射关系,
2421码
我们依然是使用四个二进制位来表示一个十进制位,不过这四个的权值是2421,同样需要注意0 ~ 4第一位都是零,5 ~ 9第一位则一定是1 这也是为了避免同一个值有不同的2421码(如5 0101或1011)
回顾
2.1.3 无符号整数的表示和运算
这里主要探讨两个问题,无符号整数,在计算机硬件内,如何表示,无符号整数的加法,减法运算时怎么用硬件实现的
机器字长限定了每一次只能进行几个bit运算,机器字长也限制了通用寄存器只能有多少位
无符号整数
全部二进制位都是数值位,没有符号位,第i位的位权是 2的i-1次方,n bit无符号整数表示的范围0~2的n次方-1 超出则溢出,意味着计算机无法一次处理这么多,可以表示的最小的数全是0,可以表示的最大的数全是1
无符号整数的减法运算
被减数不变,减数全部按位取反,末位+1 减法变加法,从最低为开始,按位相加,并往最高位进位
知识点回顾
2.1.4 带符号整数的表示和运算(原反补)
首先我们这节主要解决的是带符号整数,在计算机硬件内,如何表示,第二带符号整数的加法,减法运算是如何用硬件实现的?
同一个带符号整数可以用不同的编码方式表示 ,这便是原码 补码 反码,形式不同但是含义相同
原码表示法
分为符号位和数值位 符号位0正1负 其实也就是之前的表示方式,不过是使用一位来表示正负,其他的依然如之前的表示,注意这里假设的机器字长是n+1
原码的缺点:符号位不能参与运算,需要设计复杂的硬件电路才能处理,所以聪明的科学家也就想到了用补码来表示真值——符号位可以参与运算(正数的补码可以解释为位权,负数的补码不能解释为位权)
方法 一
正数的原码,反码,补码都是不变的
负数的原码到反码是符号位不变,数值位取反,然后末位+1得到补码
若是让你根据补码来求反码,你可以先求原码再求反码(这里使用的方式是第二种,从右往左找到第一个1 这个1左边的所有数值位按位取反便可得到原码)
方法二
从右往左找到第一个1,这个1左边的所有“数值位”按位取反(按照之前我们计算机计算的方法,把所有的数值位按位取反,末位加一个一,若是反码最后一个是一,并且这个一前面也是一,就会导致不断的向前进位,直到前面那个是零才会停止,也就导致从右往左第一个1的右边的值与原码是一致的,所以这也就是为什么我们从右往左找到第一个1,这个1左边的所有数值按位取反便可得到补码)
方法一是计算机处理的方式,我们若是手算的话 推荐第二种
带符号整数加法运算
从低位开始,按位相加(符号位参与运算),并往更高位 进位
带符号整数减法运算
A-B=A+(-B),也就是将减数取负值,所以也就有了全部位取反
方法一:首先是全部位按位取反,然后末位加一,与上面负数求补码有所不同(符号位不变,数值位取反)
方法二:与之前类似,从右往左找到第一个1,此1左边的全部取反(之前负数求补码是数值位取反,这里是全部),右边的不变便可得到原码或者补码
这也就能和之前的无符号的减法相联系,减数 全部取反,末位加1,相联系
知识点回顾
2.1.5原反补码的特性对比
注意加红的即可,如若是-64-64 结果保存在原码中则会溢出,若是保存于补码中则不会溢出
1个字节能表现的最小的负数是-128(补码),随手用“负数源码的补码等于源码绝对值取反加1”这个公式验算了一下,发现这个公式在 -128这个数上居然不管用,由于源码的取值范围是-127~ (-0),(0)~+127,所以这个公式就无法使用了,简单的说,单字节有符号数源码的 定义域不包括+/-128,故这个公式遇到-128的时候就失去了作用,只能换一个方法计算-128的补码了,即用最大的负数-1取不断的减1,一直减到下溢,那么下溢前的最后一个数就是最小的负数了,即-128(10000000B)
2.1.6 移码
补码的基础上将符号位取反
存储的值是一个环,从0000 0000开始,到0111 1111为最大正数值,再加1为1000 0000为最小负数值
2.1.7 定点小数
反码,补码和上面是一样的 这里看一下区别
定点小数是低位补零,定点整数是高位补零,同时注意这里补零的个数
另外一个需要注意的地方就是取值范围以及最小的数,还有真值零的表示
2.2.0 奇偶校验码(大纲已删)
在有效信息位的首部或者尾部加上一位奇偶校验位
奇校验码:整个校验码(有效信息位和校验位) 中“1”的个数为奇数个
偶校验码:整个校验码(有效信息位和校验位)中“1”的个数为偶数
其实也就是数给定的编码中1的个数, 若是奇校验码,其中有效信息码中1的个数为奇数个,则校验位添加0 若是有效信息码中1的个数为偶数个,则校验位添加1,
偶校验的硬件实现,各信息进行异或(模2加)运算,得到的结果即为偶校验位,然后进行偶校验(所有位进行异或,若结果为1,说明出错,但是若是同时有两个bit发生错误,则进行偶校验也是不能发现错误的)
2.2.1 电路的基本原理 加法器设计
这里主要讲三个部分,算数逻辑单元的作用,大致原理,电路基础知识,加法器的实现,与类似C语言&& 表达式Y=A*B “或”类似“||” 表示式Y=A+B,但是要注意优先级“与”是大于“或”的,同时满足分配律以及结合律如A(C+D)=AC+AD ,再如ABC=A(BC),异或相同是零,相异是一 同或 相同是一,相异是零,与异或正好相反
一位全加器两个本位和一个来自低位的进位可以确定本位的和并且也能确定应该向高位进一个什么样的值,
串行加法器
只有一个全加器,数据逐位串行送入加法器中进行运算,进行触发器用来寄存进位信号,以便参与下一次运算,如果操作数长n位,加法就要分n此进行,每次产生一位和,并且串行逐位地送回寄存器,所以这张串行加法器的效率较低
并行加法器
把n个全加器串联起来,就可以进行两个n位数的相加,串行又称为行波进位,每一级进行直接依赖于前一级的进位,既进行信号是逐级形成的,所以这种加法器的快慢却决于每一位进位的速度
本节总览
2.2.2 并行进位加法器
上述的时候我们讲过 速度很大程度上取决于进位的速度,这里我们可以发现进位的表达式又可以用更低一位的进位表达,这里也就是数学中的递推法 最终我们发现每一级是可以使用C0表示的,也就意味着我们可以直接算出每一个全加器的值,也就意味着每一个进位几乎都是同时产生的,但是这样也有一个缺点就是会导致设计的电路越来越复杂,所以通常是有四个全加器和一些运算逻辑组成
2.2.3 补码加减运算器
也就是从硬件的角度来看补码的加减运算是如何实现的,如下图,若是我们进行的是X+Y 则此时Sub也就是0 此时控制多路选择器 Y的值直接通过,若是X-Y 此时Sub也就是1,此时控制多路选择器打开1这个开关,而Y也要进行非操作,此时再加上sub 中的这个一,也就实现了减法变加法(全部位取反,末位值加一)
如下 计算机的底层逻辑在处理加法或者减法的时候是,无论是有符号数还是无符号数都是通过同一个电路来处理的,但是最后我们判断是否溢出的时候,有符号数的判断逻辑和无符号数的判断逻辑是存在显著的区别的
2.2.4 标志位的生成
两个nbit的数相加,除了生成一个nbit的值外 同时也会生成四个标志位如下
2.2.5 定点数的移位运算
移位:通过改变各个数码位和小数点的相对位置,从而改变数码位的位权,可用移位运算实现乘法和除法,原码的算数移位——符号位保持不变,仅对数值位进行移动,右移:高位补0,低位舍弃,若舍弃的位=0,则相当于/2 若舍弃的位!=0 则会丢失精度,其实这些也是可以理解的,原码到反码的过程中有一个是全部取反,自然左边高位是补一,而反码又要加一,自然作用到补码上低位也就是补零
循环移位
不带进位位:用移出的位补上空缺,带进位位,移出的位放到进位位,原进位位补上空缺
总结# 2.2.6
2.2.6.1 原码的乘法运算
这节主要讲三个问题,乘法运算的实现思想,原码的一位乘法,补码的一位乘法
乘法运算的实现思想将乘数拆成多个数相加,再用被乘数分别与这些乘数进行相乘再相加,但是这里考虑到机器实现有三个问题,1,实际数字有正负,符号位如何处理?,2,乘积的位数扩大一倍,如何处理?,3,4个位积都要保存下来最后统一相加?
问题一:符号位单独处理,符号位=A异或B
问题二:先加法再移位 重复n次,当前位=1,则ACC加上被乘数,当前位=0,则ACC加上0,每次乘完之后 在进行移位,然后乘积高位往右移动,继续看乘数的乘低位,为1则与乘积高位相加,结果放在乘积高位中,在移动,再继续看乘积低位
问题三:你会发现这里的结果不是每一个算出来 然后相加 而是一位算出来就放在ACC与MQ中了
这里使用的是双符号位,但是使用单符号位也不会出错,至于这里为什么使用双符号位,可能是因为补码的乘法一定要使用双符号位,这里可能是与补码保持统一
2.2.6.2 补码的乘法运算
和原码的移位加法相似,但是还需要多来一次加法,最后的这一次加法会让乘数的符号位也参与运算,只有加法没有移位,如下图MQ红色部分既是这里所说的辅助位,所有寄存器的长度一般都是统一的,所以这里的补码采用的是双符号位的形式,
如对下图的解析,第一步的时候,辅助位-MQ中的最低位为-1,这个时候加上乘数的补码 然后ACC和MQ统一右移,符号位不动,数值位右移,正数右移补0 负数右移补1(符号位是啥就补啥),Y5是这里的辅助位,Y4是这里MQ中的最低位
知识点回顾
2.2.7.1
原码的除法运算
如下图ACC中保留的是被除数 MQ中保留的是商 通用寄存器中保留的是除数,本来我们的想法是比较ACC与通用寄存器中的值来确定商的值,但是计算机很傻,会先默认商一,若是检查到ACC中的符号位是1(负)此时也就会修改商上面的值让其为0 并且让ACC恢复原样,然后减去除数,ACC与MQ整体左移低位补零,然后依然是默认商1,若是最后一步商余数为负,也需要回复余数并商零
恢复余数法(手算)
根据所得余数的符号位的正负来确定商应该是0或者1
不恢复余数法(手算)
2.2.7.2 补码的除法运算
2.2.7.2 补码的除法运算
2.2.8 c语言的类型转换
C语言中定点整数是用“补码”存储的
所以进行强制转化的时候
无符号数和有符号数:不改变数据内容,改变解释方式
长整数变短整数:高位截断,保留低位
短整数变长整数:符号扩展
2.2.9 数据的存储和排列
大小端模式
小段读取的方式更有利于机器的处理:计算机首先从计算机读入的最低有效字节 这样CUP在处理加法的时候,这样从低有效字节读入是有利于处理的
边界对齐
这个东西通常是结构体定义的时候,比如下图我们定义了三个char型变量 三个short型变量,还有一个short型变量,若是按照边界不对齐的方式,我们读取第一个short变量的时候需要两次访问并进行拼接,而上边界对齐则一次访问便可,且不需要拼接,一种空间换取时间的策略
2.3.1 浮点数的表示
浮点数的作用和基本原理
定点数可表示的数字范围有限,但我们不能无限制地增加数据的长度
将一个数值用阶码和尾数来表示,这样表示的数值的范围就大大增加了,
浮点数规格化
尾数的最高位是无效位会丧失精度,规定尾数的最高数值位必须是一个有效值
左规:当浮点数运算的结果为非规格化时要进行规格化处理,讲尾数算数左移一位,阶码减一
右规:当浮点数运算的结果尾数出现溢出,(双符号位为01或10,双符号位中的更高位表示我们当前数值的正负性)时,将尾数算数右移一位,新空出的位置与与双符号位保持一致,这里也就是零,最后阶码加一
采用双符号位,当溢出发生时候,可以挽救,更高的符号位是正确的符号位
浮点数的表示范围
这里要注意用补码表示的负数的尾数,我们为了计算机处理起来方便,也就是当符号位为0的时候 数值位为1 当符号位为1的时候数值位为0,如下图右下的例题,你发现1.1110100并不满足符号位与最高位是相反的 所以需要移位,我们知道负数的补码是补1的,并且规格化是需最高位为0的,所以也就需要算数左移三位,此时阶码值就要减3
知识点回顾
2.3.2 IEEE754
移码
我们上面说过阶码可以使用移码或者补码来,尾数也可以使用原码或者补码来表示,所以也就需要某些标准,
补码的基础上将符号位取反就能得到移码,注意移码只能用于表示整数
移码的定义:移码=真值+偏置值,此处8位移码的偏置值=128d=1000 0000B 偏置值一般取128D 此时移码=补码符号位取反,IEEEE754取的偏置值127时,此时对于真值-128=1000 0000B 移码=-1000 0000 +0111 1111=1111 1111(这里的计算时是发现被减数比减数要小,由于我们移码只有8bit,所以背后的这些加减运算都会进行mod128,我们可以在原有的基础上加上128,然后再减 此时得到的移码便是1111 1111)
IEEE754
这个表格需要记住,并且在计算时,可以将这个移码看成一个无符号数,然后用之前的计算方式 比如下图double中的蓝色部分的,可以看成无符号数128(移码)-1023(偏移量)
这里可以将其转化成对应的十进制相加减,比如1111111(127)-1结果也就是126 用八位表示,并且要将其看成是无符号数,所以表达的方式就是0111 1110,尾数部分的个数是需要进行拼凑的,一共凑成32位即可
数值范围
之前我们说过-128(全1) -127(全0)有其他用处 所以这里阶码的最小值时-126,所以范围如下
虽然在偏置值为127 时,移码全0 事实上的对应的-127次方,但是这里下图我们会把它固定的视为-126次方,此时是正无穷还是负无穷是看其中的数符位
2.2.3 浮点数的运算
本节主要讲的是浮点数的加减法运算,以及强制类型转换
小阶向大阶靠齐是为了计算机内部硬件的实现方便
它的两个符号位是否相同 相同则没有越界,如这里的11 就没有越界
如下面这题我们还有第零步,需要转化成真值的形式,然后这里首先将 -101 转换成补码的形式,也就是1011(取反加一)然后这里题目要求阶符取两位,所以这里需要双符号位,也就是11011 ,接下来来看尾数-0.101,他所对应的原码是1.101 他的补码是1.011,同样的需要两个符号位,所以这里也就是11.011 然后根据题目所说尾数取9位,进行扩展即可,将阶码以及尾数部分拼接起来便可得到x
这里对阶求阶差,本来是减法,但是计算机中只有加法,所以将后面改成负数的补码 也就是全部位取反,在加一便可,然后再将得到的结果转化成原码,两个符号位不变,其余位取反加一便可这里也就是-1,下一步尾数相减 同样的道理也是减数取负数的补码形式,这里发现双符号位发生了变化也就是尾数发生了溢出,这里就需要尾数右移 然后阶码加一,此时就完成了规格化,判溢出的方法是阶码加一,判断两个阶符是否相同,相同则没有溢出
舍入问题
除了右规的时候会面临舍入的问题,有的计算机可能会浮点数的尾数部分单独拆出来计算24bit->32bit 算完结果在经过舍入32bit->24bit再拼回浮点数,发生下溢我们直接将将其当成
机器数零便可,若是发生上溢则需要中断处理,上溢出是我们必须要处理的错误
本节回顾
3.1 存储系统基本概念
存储器的层次结构
手机里面的辅存,也不是用磁盘来进行存储的,手机里面存储的软件什么的就是存储在辅存中的,但是cpu不能直接和辅存进行交互,当我们启动一个app,需要先将数据从辅存拿到主存中,这个时间是较长的,我们增加一个高速缓冲存储器是因为尽管我们的读写速度已经很快了,但是还是没有cpu 处理的速度快,所以计算机把那些有可能频繁访问的数据放在cache中,这样读取的速度也就更快
存储器的分类
存储不仅可以按照层次来进行分类
存储器也可以按照存储介质来进行分类以半导体器件存储信息,以磁性材料存储信息,以光介质存储信息,
还可以按照存取方式来进行分类,随机存取寄存器(RAM):读写任何一个存储单元所需时间都相同,与存储单元所在的物理位置无关,顺序存取寄存器(SAM)读写一个存储单元所需时间取决于存储单元的物理位置,直接存取存储器(DAM)既有随机存取特性,也有顺序存取特性,先直接选取信息所在区域,然后按顺序方式存取(磁头臂要前后移动,移动到要读写的那个区域,中间的马达带动磁盘进行转),后面这两种又称为串行访问存储器,读写某个存储单元所需要时间与存储单元的物理位置有关,这三种是根据地址来读写,还有一种是相联存储器:也可以按内容访问的存储器,可以按照内容检索到存储位置进行读写,“快表”就是一种相联存储器
按照信息的可保存性进行分类:断电后,存储信息消失的存储器,易失性存储器(主存,Cache,如手机关机后再开机很缓慢,这是因为本来信息丢失,重新将操作系统调入主存也是需要时间的,),断电后,存储信息依然保持的存储器——非易失性存储器(磁盘,光盘)
存储器的性能指标
1,存储容量:存储字数*存储字长(之前有提到过MDR位数反映存储字长,MAR又反映了存储字数是多少)
2,单位成本:每位价格=从成本/总容量
3,存储速度:数据传输率=数据的宽度/存储周期(数据的宽度即存储字长,存储周期,每个存储周期我们可以都或者写一个存储字这么多的数据)
知识回顾
主存——辅存:实现虚拟存储系统,解决了主存容量不够的问题
Cache——主存:解决了主存于cpu速度不匹配的问题
3.2.1 主存储器的基本组成
本节主要讲三个部分:半导体元件的原理,存储芯片的基本原理,如何实现不同的寻址方式,这里我们先学习半导体元器件存储0和1的原理,然后我们可以构成所谓的存储芯片,又因为存储芯片中存储了很多字的信息,所以存储芯片必须提供寻址的功能,最后我们来探讨不同的寻址方式如何实现
基本的半导体元件及原理
比如这里的MOS管,可以将MOS管理解为用电来控制的开关,若是木有施加电压,或者施加的电压不足5V,那么这个MOS管就是绝缘体,就是不导电的,只有当上面接通的时候,这个电容才能存储电荷,所以我们可以根据电容中是否含有电荷信息来确定表示零或者1,当我们要在电容中写入的时候不仅要接通MOS管上面的的那个线路,而且还要接通MOS管下面的线路,这样就可以写入电容,如下图本来电容中已经存储了电荷,当我们施加一个五伏的电压在这个红色的线上的时候,接通了MOS管,此时这些0,或者1 就是顺着这条绿色的线导出,这样的一整行就是我们提到的存储单元,也就是一个存储字,所以一个存储子多少个bit具体要看存储体的具体结构是怎么样的,而多个存储单元也就构成了一个存储体,我们一次可以读出的就是一个存储字,就像下图的,这里的存储体只包含了两个存储单元
接下来我们要研究的就是如何根据地址来读或者要写那个存储字,这就涉及到译码器的使用,我们给出n位地址,就会对应2的n次方个存储单元,会根据地址将其转化成某一条字选线的高电平 然后根据这条绿色的线也就是数据线(位线),将其传送到MDR中,然后数据总线会从MDR中取走所有的数据,数据总线的宽度应该与存储字长是相同的总容量=存储单元个数*存储字长
比如CPU通过地址总线将地址送到MAR中,但是由于是使用电信号的方式,电信号可能不太稳定,只有当MAR稳定之后,控制电路才会打开译码器的开关,同样的只有输出的信号稳定之后,控制电路才会认为此时的输出的正确无误的,另外存储芯片还需要向外提供一些线路 通常是片选线(作用是读指定芯片),通常是CS上一个扛 或者CE上一个杠,当表示它是低电平的时候是有效的
有的题目若是让你计算存储芯片引脚线路的个数,也就是计算地址线,数据线,片选线(有多个芯片,作用是选择哪一个芯片)读写线(可能是一个也可以是有两个)
寻址
现代计算机通常按字节编址(每个字节)即每个字节对应一个地址,按字节寻址,按字寻址,按半字寻址,按双字寻址,如下 若是总容量是1kB,这样的一整行表示的是一个存储字,每一个存储字是4B,所以也就有256个存储字,现代计算机通常是按照字节进行编址,也就是每一个字节对应一个地址,有1K个字节,自然也就有1k个地址,这样自然也就有10个地址线,也就是从十个全0 到十个全1这个范围,我们只需要将字地址算数左移两位,就可以将字地址转换成字节地址,比如我们要读的是1号字,我们算数左移两位,就是末位填两个0也就是4 也就得到这个字它起始字节的地址, ,也就是虽然通常是按照字节进行寻址的,但是却也有按照字寻址,按半字寻址
本节回顾
3.2.2 SRAM DRAM
DRAM用于主存,SRAM用于Cache,所以本节我们首先来根据存储元件的不同来介绍为什么会出现不同的差异,还有就是DRAM的刷新,DRAM的地址线复用技术
存储元的不同
上面说过DRAM这种存储元所使用的栅极电容存储0或1的方式,但是当电容放电信息被破坏,是破坏性读出,读出后应有重写操作,也称“再生”,所以这种读出更慢,因为要重生,而且这个只需要一个MOS管,每个存储元制造成本更低,因此常被用来制造主存,集成度低,功耗高,并且电容里面的电荷也会逐渐流失,因此我们只有不断的刷新,并且由于集成度低,这里对应的行列地址的位数也比较少,所以我们同时把行列地址送过去便可
双稳态触发器,我们规定A高电平B低电平是为1,A低B高是为0,这里我们可以根据左边或者右边那一条输出了一个低电平信号,就可以判断是0或者1,而这种双稳态则是非破坏性的读出,无需重写,这种读出快一点,所以常被用来制造高速缓存,这个需要6个MOS管,因此体积更大,每个存储元制造成本更高,集成度低,多个元器件联合使用使用功耗大,而DRAM(也就是栅极电容的)则需要分两次送(地址线复用技术,往下看有解释)
DRAM的刷新
当需要的存储单元的个数过多的时候,对应的选通线也将会过多,将一维的排列变成二维的排列,原来的n位地址会被拆分成行地址和列地址,地址的前半部分会被看成行地址,后半部分是列地址,
本节回顾
就如之前所讲,需要有n位地址线来同时传送行或列,但是使用地址线复用技术,也就是只用n/2个地址线,先传行地址送入到行地址缓冲器,然后再传列地址到列地址缓冲器中,可以让地址线更少,芯片引脚也就更少,但是对于SRAM因为存储元较大,自然集成度低,自然对应的地址线的数目也会少,同时送便可
3.2.3 只读存储器ROM
RAM芯片–易失性,断电后数据消失
ROM芯片–非易失性。断电后数据不会丢失
许多的固态硬盘的存储单元是闪存,因为有多个存储单元,所以也需要控制单元
本节回顾
3.3.1 主存储器与CPU的连接
这小节我们主要讲单块存储芯片与CPU的连接,多块存储芯片与CPU的连接,分别是位扩展法,字扩展法,以及字位扩展法,本节的最后写了关于译码知识的补充,我们现在计算机的64位指的是数据总线的长度是64位,也就是使用位扩展法
之前我们所说MAR,MDR寄存器都是存放于存储芯片中的,但是现代计算机通常都是将MAR与MDR存放于CPU内部,存储芯片中一个普通的寄存器用于暂存输入输出数据
位扩展
其中每一块存储芯片中前面的8K需要13根地址总线,后面的1 也就需要一个数据总线,所以cpu的数据总线并没有被充分的利用,这里将不同存储芯片的地址总线连接到一起,这样13位的地址信息可以选择到多块芯片相同的存储单元,存储字长扩展到了8bit,这里的CS可以一直接通,是没有关系的。
字扩展
如下图这个存储芯片的存储字长已经是8位了,芯片所能处理的宽度与cpu所能处理的宽度是能完美匹配的,但是我们发现cpu的寻址能力是有2的16 次方吗,而我们只是用了13 位,若是想充分利用,若是和上面一样存储芯片的地址总线连接在一起,CS同时工作,则两个存储单元的8bit的信息都会顺着数据总线传向CPU ,同时传就会导致一个数据总线的一个冲突,这里的一个方案是假如CPU有n条多余的地址线,让多余的连接每一个芯片的片选线CS,也就只能有n个片选信号,同时也能发现地址是01的时候选择的都是左边的这个芯片,01的时候选择的都是右边的这个芯片。但是你也会发现这样是不连续的地址空间。
加入一个非门,也可以看作是一个1-2 译码器,这样地址信息便是连续的,这种m-n译码器就像左边010表示的是真值2,则右边的第三个片选线被接通
这里每一个芯片的A0到A12都是直接与cpu相连的,这里画一起是不想太乱,并且地址也是相连的
当然考试的时候可能给你一点陷阱就是中间A14没有连接,正常连接本来有8k个合法地址对应第一个存储芯片,若是中间A14没有连接,则每一个芯片对应的就是有16K个合法的地址
强调
位扩展可以使得存储器的字长变得更长,从而发挥数据总线的数据传输能力,字扩展可以增加存储器的存储字数,可以更好的利用CPU的寻址能力
字位同时扩展
如下每一个芯片的存储单元是4位的,也就是需要四根数据总线便可,所以可以进行位扩展,比如1号可以连接地址线的低四位,2号可以连接地址线的高四位,然后再进行字扩展即可,每一个芯片的字数是16k也就需要14根地址线,所以还剩余两个地址线未使用,上面使用的是2-4 译码器这也就导致使用的主存空间是连续的
补充译码器
注意这里带圆圈表示的是取反
本节回顾
3.3.2 双端口RAM和多模块存储器
之前说过DRAM是电容存取,并且会自动放电,所以每次存取都是需要恢复时间,并且现在手机都是多核的 当多个cpu访问的时候,怎么处理
双端口RAM
两个cpu就可以通过它的两个端口来访问RAM,这样就需要主板有两组完全独立的数据线,地址线,控制线,CPU,RAM 中也要有更复杂的控制电路,当两个端口进行的操作是非法的时候,应该置忙的信号
多体并行存储器
即使是单核的cpu访问内存的速度较快,每一次读写之后都需要恢复时间,一个解决的方式是使用多体并行存储器,CPU对内存进行访问的时候一定是需要提供地址,高位交叉编址指的是地址的高位用来判断使用的是哪一个存储体,后面的低位表示的是体内地址,可以将其理解位四根内存条 体号表示的是选择的是M0 M1 还是什么,然后来看高位交叉编址的地址是竖着编号的,而低位交叉编址是横着编的
宏观上读写一个字的时间接近R,若是我们连续的访问一系列内存,至于为什么讨论的是连续的空间,是因为许多的应用都是连续的存放于主存当中,若是高位交叉编址方式每个存取时间是r,后面的3r时间等存储体恢复,才能进行下一个存取,读取五个连续的存储空间5T,若是使用地位交叉编址,过了r之后对M0的存取就已经结束了 后面的3r cpu不需要管他,让他自己恢复便可,当M3 读取完之后M0已近恢复了,M0又可以被读取了,读取5 个连续 的存储空间则需要2T个存取周期,
应取几个“体”
当m<T/r的时候CPU需要多余的r的时间继续进行等待M0刷新完成,若是m>T/r,M0这个存储体会有一段时间是闲置的,各个存储体没有办法发挥到它们的极限,所以模块数=T/R的时候流水线的效率达到顶峰,同时存储体的数量最少,也就是成本最低,每个模块都有相同的容量和存取速度,各模块都有独立的读写控制电路,地址寄存器和数据寄存器,它们既能并行的工作,又能交叉工作,可以有选择的读取某个模块的某个字
多模块存储器
单体多字存储器相当于是存储体的合并,本来我们只能读取一个字,但是通过这样的扩展,我们每一次可以读取多个字,这也就需要对总线宽度进行扩展,同时若是我们读取的是2345 这几个存储单元,若是使用的是下面的单体多字存储器,则需要分两次读取,并且每一次读取会有yong余,若是用上面的多体并行存储器则可以根据地址精准命中
当m=T/r的时候,两者的效率几乎差不多
本节回顾
实际用处
给自己的电脑插了两个内存条之后,给这两个内存条采用的是低位交叉编址的方案,这样几乎可以使得内存的吞吐量几乎翻倍,如果你买的是两个主频不一样的内存条 ,主频高的将进行降频处理,将会有所浪费,选择的如果不是相同容量的,低地址部分组成双通道的形式,高地址依然是单通道的形式,这样电脑的性能就不稳定,所以应该插入颜色相同的卡槽
3.4.1 磁盘存储器
我们在磁性盘面上涂磁性材料的方式是一圈一圈的涂的,也就是磁道,这里绿色的圈就是磁道,为了方便主机对磁盘数据的读写,我们将磁道划分成一个个更小的扇区,每个磁盘有多个盘面 ,每个盘面也对应一个读写磁头,比如这里就是有四个盘面 ,相对位置上的磁道我们将其称为一个柱面,也就意味着一个磁盘上有多少个磁道就有多少个柱面,
尽管内侧较短,但是存储的位信息是一样的,这样就意味着越靠经内测的,它的位密度越大,越靠近外侧的它的位密度会越小,所以许多的工厂是受到这里规则的限制,旋转延迟时间也就是磁头定位到所在扇区所需要的时间,这里通常是转半圈所需要的一个时间,因为在任何扇区的概率是相同的,
无校验功能也就是当某些扇区上的数据发生损坏的时候,我们就不能恢复数据,镜像磁盘阵列也就是设置一个同样的磁盘阵列,用于防止数据的丢失,但是也就意味着空间利用率只有一半 , 四位信息位对应的三位的海明校验码,就有纠正一位错 ,发现两位错的能力,这里的技术也就会用于比如百度云这样的公司
本节回顾
3.4.2 固态硬盘SSD
这些黑色的小芯片就是用于存储数据的,是基于闪存技术,每个闪存芯片是由多个闪存块组成,而每一个块又可以拆成一个个的页,若是数据存储与固态硬盘中,则系统要读或者写的逻辑块,也就对应这里的页,当我们要写入数据的时候,但是因为是以页为单位的,并且需要擦除,若是其中已有数据,这里我们就会先将数据进行迁移之后在进行写入,但是发生了数据迁移,这样也就需要闪存翻译层进行重新的映射,这也就导致了固态硬盘读的速度远远高于写的速度
3.5.1 Cache的基本概念和原理
局部性原理
由于循环结构的存在,其中的数据比如说i,也是可能在时间上循环的存取,由于局部性原理,这也就意味着,当程序是按照列优先进行访问的时候,由于空间局部性较差,也就意味着所需要的时间更长
性能分析
知识回顾
3.5.2 Cache和主存的映射方式
之前我们说过Cache保存的是主存中某些数据的副本,映射方式探讨的就是这个主体,这节将会介绍三种方式,如下图,但是全相连映射也有一个问题,就是这里我们的标记使用的也是0,1 的bit,这也就也为着这个标记可能需要的bit也很大,并且开始的时候初始化都是0,这也可能不对,因为我们可能解析为主存上0的位置的信息,所以这里我们还需要另外一个有效位,主存地址的前nbit,对比Cache中所有的块的标记,若标记匹配且有效位=1 则Cache命中,访问块内地址为某某的单元,若是未命中或者有效位=0,则正常访问主存
全相联映射
直接映射
如下图 前面的19位可以作为Cache的一个行标记,后面的三位可以反映每一个主存标记可以放在哪一个Cache行
组相联映射
每个主存块的后两位反映了分组的组号是多少,这也就意味着后两位相同的主存块号一定是在一个组内的,这也就意味着我们标记位只需要20位即可
知识回顾
3.5.3 Cache替换算法
Cache很小,主存很大,如果Cache满了怎么办?
替换算法
这也就是本小节要处理的问题,若是直接映射,则不需要考虑替换算法,因为若是对应的位置非空,则毫无选择的直接替换即可,所以替换算法只会被用到全相联和组相联映射,这节我们主要学习四种替换算法,随机算法,先进先出算法,近期最少使用,最近不经常使用
随机算法
先进先出
这里没有考虑到局部性原理,如我们写C语言中,若是第一步就使用了print 后面也可能会用到print,抖动现象:频繁的换入换出现象(刚被提替的块很快又被调入)
近期最少使用算法
做题的时候,我们可以从当前访问的一个主存块号,往前看,看哪一个是最近被访问过的,没有出现的就是要被替代的主存号,这里比起高的没有加一,是因为即使不加1,它依然是最大的数,加一毫无意义,所以我们只有四个计数器的时候,我们最大值应为3,不会达到4,Cache块的总数是2的n次方,则计数器只需n位,且Cache装满后所有的计数器的值一定不重复,命中时,所命中的行的计数器清零,比其低的计数器加1,其余不变,未命中且还有空闲行时,新装入的行的计数器置0,其余非空闲全加一,未命中且无空闲行时,计数值最大的行的信息块被淘汰,新装行的块的计数器置0,其余全加1
不经常使用算法
经常被访问的主存块在未来不一定会用到,(如微信视频聊天相关的块) 并没有很好的遵循局部性原理,因此实际运行效果不如最近最少使用算法
知识回顾
3.5.4 Cache写策略
CPU修改了Cache中的数据副本,如何确保主存中数据母本的一致性?
Chche写策略
这节写策略分为写命中(全写法,写回法),以及写不命中(写分配法,非写分配法),
写命中
我们可以根据脏位来确定数据是否修改过,根据标记位来确定需要写回到什么位置
全写法
当CPU对Cache写命中时,必须把数据同时写入Cache和主存,一般使用写缓存,访存次数增加,速度变慢,但是能保证数据的一致性,这里由于SRAM实现的写缓冲,所以cpu与写缓冲的交互式比与主存的交互要快的,并且有专门的控制电路控制下逐一写回
写不命中
多级Cache
知识回顾
3.6.1 页式存储
这个分页 更多的上是逻辑上的划分,而主存和Cache更多的是物理层面上的一个划分
我们作为程序员只能是给出一个逻辑地址,而操作系统则可以根据这个逻辑地址去找相应的物理地址,下图是首先根据逻辑地址前两位找到相对应的操作系统被划分的0号页面,然后我们可以看出0号页面被划分到二号主存块中,然后根据主存块号,以及页内地址的拼接 转化成实际的物理地址,这个步骤中最重要的就是建立一个逻辑页号到主存块号之间的关系,操作系统会建立一个页表,cpu执行的机器指令中,使用的是“逻辑地址” 因此需要通过“页表”将逻辑地址转为物理地址,页表的作用:记录了每个逻辑页面存放在哪个主存块中,cpu中还会有一个重要的页表基址寄存器,这个寄存器指明了页表在主存中的存放地址,然后我们又知道每一个页表项的大小是固定的,这样我们就知道了每一个页表项所在的位置
快表的引入
类似于主存设置一个Cache,这里我们可以将页表中经常使用的页表项单独存放于一张块表中,可以加快地址的变换的速度,快表的作用是加快逻辑地址到物理地址的转化,而Cache则是加快对数据的访问
知识回顾文章来源:https://www.toymoban.com/news/detail-420812.html
3.6.2 虚拟存储器
段式虚拟存储器
这里由于虚拟地址也是按照段号和段内地址来分的,但是由于段长不一样,这里我们需要将段表加上段长,我们的主存不会再进行分块或者分页,所以我们需要记录一下每一段的首地址
段页式虚拟存储器文章来源地址https://www.toymoban.com/news/detail-420812.html
到了这里,关于计算机组成原理汇总的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!