一. 早期的计算机
最早的计算器是 算盘 🧮
Computer 最早指代 专门来算数的人,他们少量依靠机器(算盘),大量还是靠自己
当然面对大量的重复计算,科学家会设计一些精妙的计算机来保证准确性 节省人工成本
1.2 差分机
是英国科学家查尔斯·巴贝奇研发的自动化数学机器的基本想法:
利用“机器”将计算到印刷的过程全部自动化,全面去除人为疏失(如:计算错误、抄写错误、校对错误、印制错误等)。而差分机一号(Difference Engine No.1)则是利用N次多项式求值会有共通的N次阶差的特性,以齿轮运转,带动十进位的数值相加减、进位
在1880年代,美国人口普查 导致了 计算问题的爆炸:如果用之前的方式,10年一次的人口普查,计算需要13年
二. 电子计算机
2.1 打孔卡片制表机(Tabulation Machine)
可以从卡片上的特定排列的孔洞分析出数据来
并且还是电动的,计算效率提升10倍。
人口普查一战成名,保险 金融公司看到了计算的强大,于是赫尔曼 创建了 制表机器公司(Tabulating Machine Company) 。1911年,和其他几家合并 成为 IBM
随着人口的爆炸,各种需求越来越多,计算机越来越大
2.2 继电器
全自动化循序控制计算机(Automatic Sequence Controlled Calculator,缩写为ASCC)
ASCC是由开关、继电器、转轴以及离合器所构成。它使用了765,000个组件以及几百哩长的电线,组装大小为16米(51呎)长,2.4米(8呎)高,2呎深。重达4500公斤(5短吨)。其基本计算单元使用同步式机械,所以它有一跟长15米(50呎)的传动轴,并由一颗4千瓦的马达所驱动。马可一号可以存储72组数据,每组数据有23位十进制数字。每秒可执行3次加法或是减法。一个乘法则须6秒,一个除法须15.3秒,计算一个对数或是一个三角函数需花费超过一分钟。
2.2.1 Mark I
继电器 --------> 马达 --------> value ++ (有点像制表机)
缺点: 继电器的金属有重量,开关切换不会太迅速(1940,50次/s)
Mark I 有3500个继电器,磨损相当可怕 带来不稳定性
这些继电器工作还会带来大量的热🔥,吸引昆虫,因此 说出问题:有bug(虫子)
因此,需要一个更高效可靠的来代替继电器
2.3 二极管
首台 二极管 电子计算机,用来给英国破解德国的密码
(和图灵机 作用类似,但是图灵机不属于电子计算机)
2.3.1 巨人计算机
简单来说:可以通过控制电荷来达到控制电路开关的功能。
优点:不用真的物理开关电路了,速度大大加快,这个改进统治了以后半个世纪
缺点:二极管灯泡也会烧掉,体积也较大
在1950年,二极管达到顶峰
2.4 晶体管
通过控制这个 半导体的 电荷,就控制 电路
速度就快多了,体积 稳定性 也提升 ,百万次/s 稳定工作10y
贝尔Lab刚做出来的时候就引起了轰动
2.4.1 IBM608
IBM 608晶体管计算器是一种插接式可编程单元,是首个使用不带任何真空管的晶体管电路的IBM产品,被认为是世界上首个面向商业市场制造的全晶体管计算器。它于1955年4月宣布,于1957年12月发布
很多半导体 和 晶体管 的开发公司在集中在圣克拉拉谷,生产半导体用硅 硅谷因此得名
三. 布尔逻辑 & 逻辑门
之前的计算机是机电设备,一般也采用10进制
采用的原理:控制电路的通,来实现结果的+±-
控制电路的通,有以下几种方式
3.1 Not Gate
晶体管可以非常简单的实现not
3.2 And Gate
3.3 Or Gate
可以把上面3个gate做一次抽象,用简单的图形表示
3.4 XOR Gate
XOR : 和OR的不同:1 1 = 0
四.二进制
4.1 二进制的诞生
只有开关0 1 状态 ,也可以表示数据
并且有在数学界有一个数学分支存在,专门研究 01 布尔代数
英国数学家乔治 布尔
布尔值也因此得名
八位二进制 最大表是:256
8位计算机,8位图片,8位音乐:计算机同时处理8位 二进制
256不算多,意味着计算机里只能有256种颜色
8位太常见了,因此封装了一下 8bit = 1byte 1024(1000)byte = 1kb
当然也可以用二进制表示 小数 负数 字母 RGB
计算机编码
UniCode 问世前,日本人经常会被 乱码影响,日本定义了“mojibake” 乱码
4.2 算数逻辑单元 ALU
每一个对二进制的处理都需要运用到算数逻辑单元
Arithmetic Logic Unit : 对二进制的处理
ALU有两个单元: 算数单元 + 逻辑单元
4.2.1 算数单元
4.2.1.1 半加器
把两个数相加 半加器
就用到了 XOR AND 逻辑门,把这个分装成半加器
半加器 只能 处理 1 + 1
超过1 的计算 就需要用到 全加器
4.2.1.2 全加器
4.2.1.3 8位加法器
如果结果有9 位,那么就 overflow
为了防止溢出,可以用16 or 32位的全加器,代价是将会用到更多的逻辑门
12 * 5 = 12 + 12 + 12 + 12 + 12
需要5次 ALU
4.2.2 逻辑单元
and or not 等操作,称为逻辑单元
也能做一些简单的逻辑处理,例如判断是不是负数
判断一个数字是不是0
五 寄存器 内存
5.1 Memory
5.2 寄存器
抽象一下,门锁 Gated Latch
2.1 并排
但是 64位寄存器 要 64根数据线 input ,64根数据线 output,和 1根选择锁存器 64 + 64 + 1 = 129
256位要513条线
…
2.2 矩阵
允许写入线 是控制整个16*16的memory存储
1根允许写入线,1根允许输出线,1根数据线
16 + 16 根选择锁存器
12 行 8 列 = 11001000
为了将地址转换成 行和列,我们需要 多路复用器
5.3 多路复用器
0000:第一列
0001:第二列
一个多路复用器控制row
另一个多路复用器控制column
地址位相同,比如00000001 八个bit存在八个memory上
让我们再次封装,把256位的内存当成一个整体
为什么32位操作系统
256 bit memory
8位地址 8 bit address:4位代表row,4位代表cloumn
再把 8 个 256 bit memory 并排,组成一个byte的memory
每个byte的8 bit 分别存在 8ge memory上
为了存一个8 bit 数字,可以同时给8个256位内存一样的地址,每个地址存1 bit,意味着这里总共能存256个byte
KB GB 都是这么打包而成的
随着内存增大,寻址也必须扩大
8位 最多能代表256个内存地址
要给千兆 或 十亿的内存寻址,需要32位的地址
从上得知,内存可以直接读取任意的地址
所以, 随机存取存储器RandomAccessMemory 简称 RAM
六 CPU
CPU负责执行程序,各种程序给CPU指令
如果是数学指令,比如 + / - ,ALU运算
也可能是内存指令,CPU会和内存通信,然后读写
6.1 CPU的结构
6.1.1 指令地址寄存器 程序计数器(PC)
记录CPU 运行到哪里了,存储 下一条 运行的内存的地址
6.1.2 指令寄存器
从CPU获取将要执行的指令,存储在指令寄存器
6.1.3 寄存器
还需要4个而外的寄存器来参与计算
6.2 CPU的执行过程
6.2.1 取指令阶段
指令地址寄存器 会自动从0 开始,把memory中0的数据copy到 指令寄存器中
6.2.2 解码阶段
前 4位操作码 和已经存在的指令表做对应,查看指令要做什么
后 4位1110 是RAM的地址 , 14
接下来,指令由“控制单元”进行解码
6.2.3 执行阶段
电路先链接1110的memory,连接允许读取线
地址再链接到A寄存器,memory Data线 输出
这样就完成了这个指令
不同的逻辑有不同的逻辑电路解码,再次封装Control Unit
指令地址寄存器 ++
add
不能直接写到A,因为会重复+++,结果会先在控制单元保存
关闭ALU,再把结果写到A
store
把A中的结果再 回写到内存
clock
时钟控制这一切进行,不能太快,因为电传输也需要时间
CPU “取指令 —> 解码—> 执行”的速度叫“时钟速度” clock speed (单位Hertz)1 赫兹 = 1周期/s
超频也就是改的这个hz
降频可以省电,减少散热
以上就可以分装成CPU了
七 指令& 程序 & 高级CPU
给CPU 不同的指令,就会执行不同的任务
硬件被软件控制
JUMP指令:把指令地址寄存器 改为 指定位置
JUMP Negative :while( … )
内存前四位存储操作码,4 位最大16
最直接的做法就是更多位来代表指令 32位 64位
还可以设计“可变指令长度”
最早的Intel 集成CPU有46个指令,现在有上千个指令
7.2 高级CPU
之前做除法
17 / 5 = 17 - 5 - 5 - 5
现代CPU直接在硬件层设计了除法,可以直接用ALU做除法
7.2.1 提高单个CPU效率
总线 BUS CPU & RAM 之间数据传输线
取数据的时间,CPU处于空闲状体,
所以可以加一层缓存,CPU 直接和这个缓存做数据交换
缓存命中(cache hit):CPU想要的数据在缓存中
脏位(dirty bit):CPU计算完成,写入缓存 。缓存 & RAM不一致了,这种不一致必须要记录下来,之后要同步
解决脏位:
- 加载新内容前,写回RAM
- 指令流水线,并行处理
CPU计算的时候,Cache就可以交换数据,这样更能够减少CPU的空闲时间
现代高级CPU都采用 (out of order)执行
推测执行 speculative execution
CPU提前预测 jump 指令的可能性 branch prediction 分支预测,现代CPU 推测执行90% +
7.2.1 多核CPU
多核之间可以共享缓存
当然更暴力:多个CPU
八 编程
最早的编程有点像织毛毯,不同的程序就需要重新织,程序都存在插线板中
1950左右,memory商业化应用,程序开始存在内存中
并且还可以保存结果
8.1 冯诺依曼结构
定义计算机基本结构为 5 个部分,分别是运算器、控制器、存储器、输入设备、输出设备,这 5 个部分也被称为冯诺依曼模型。
我们之前实现的CPU就是冯诺依曼结构,也是现在主流计算机结构
8.1.1 input & output
最原始是用打孔卡片来把数据写入memory
输出数据,也是需要用到卡片
也可以用大量的开关来当作打孔卡片
所以,前期的编程都十分专业
8.2 编程语言
其实也就是通过 汇编语言 将编程语言翻译成机器码(二进制)
最初有多家写了 把 高级语言 翻译成 机器码的语言
8.2.1 COBOL
美国统一多家机构,做了一个统一的高级语言,可以翻译成机器码
1960 ,出现了LISP BASIC 等语言
1970,出现了C…
1980,C++ Object-C
1990 Python Java