「MoreThanJava」一文了解二进制和CPU工做原理

  • 「MoreThanJava」 宣扬的是 「学习,不止 CODE」,本系列 Java 基础教程是本身在结合各方面的知识以后,对 Java 基础的一个总回顾,旨在 「帮助新朋友快速高质量的学习」
  • 固然 不论新老朋友 我相信您均可以 从中获益。若是以为 「不错」 的朋友,欢迎 「关注 + 留言 + 分享」,文末有完整的获取连接,您的支持是我前进的最大的动力!

Part 1. 原来,咱们是这样记数的

本节内容节选自下方 参考资料 1html

在讨论「二进制」和「CPU 如何工做」以前,咱们先来讨论一下咱们生活中最稀疏日常的 数字,咱们与之频繁地打交道:一个约定的时间、一件商品的价格、一我的的身高....却不多有人细细想过,这些数字是如何表达出来的?为何你理所固然地把 1024 理解为「一千零二十四」而不是别的含义?java

也许你从未想过,在这简单的记数中,沉淀着人类的大智慧。python

一进制计数法

早在数字的概念产生以前,人类就学会了使用树枝、石子、贝壳等天然界随处可见的小物件表示猎物的、果实的、部落人口的数量。好比在某个角落堆上一堆石子,每打到 1 只猎物,就扔 1 颗石子进去,每吃掉 2 只猎物,就从中取走 2 颗石子。他们并不在乎石子的总数,只是时不时地瞅一眼,心底大体有数。git

其实这是一种最朴素的记数方式,数学家称之为 一进制记数法(unary numeral system)。咱们把它符号化一下,好比用斜杠 / 来表示:程序员

  • 1 就是 /
  • 2 就是 //
  • 4 就是 ////

好像没毛病,咱们平时掰手指用的就是这种记数法,但数字一大,场面就要失控了。github

符值相加记数法

为了解决记录大数的问题,因而咱们得发明一些其余符号来表示更大的数值,好比用横杠 - 表示 10,用十字 + 表示 100。那么:面试

  • 16 就是 -//////;
  • 32 就是 ---//;
  • 128 就是 +--////////;

漂亮....这种靠符号类型和符号数量表示数字的方法被称为 符值相加记数法(sign-value notation),古埃及和古罗马用的都是它,只不过符号各不相同。缓存

古埃及的记数符号:less

1工具

10

100

1000

10000

100000

1000000

1024 在古埃及就写做:

你会发现,符值相加记数法的一大优势是,符号的顺序能够任意打乱,数字含义不受影响。我国藏族曾用石子表示 1、木棍表示 10、果核表示 100、蚕豆表示 1000、瓦片表示 10000,那么,当你把 1 颗蚕豆、2 根木棍和 4 颗石子胡乱地攥在手里,别人依然知道它们是 1024

古罗马的作法略有不一样,他们对五进制情有独钟:

1

5

10

50

100

500

1000

I

V

X

L

C

D

M

这些符号沿用至今,想必你们(至少对前 3 个)都比较熟悉,许多钟表仍保留着使用罗马数字的习惯,1~12 分别表示为:IIIIIIIVVVIVIIVIIIIXXXIXII。你会发现,罗马记数法是符值相加记数法的变种,由于它不光「相加」,还「相减」。这种方式就不容许符号乱序了,IVVI 表示的是不一样的数字。

那罗马人何苦要使用这种更复杂的记数法呢?无非是为了读写方便。一样表示 9IXVIIII 更简洁。

其实有一种更好使的方法——用另一些列符号来表示符号的数量。好比用 A 表示 1 个符号,用 B 表示 2 个符号,以此类推,用 I 表示 9 个符号。

如此,上文表示 256++-----////// 就能够写做 B+E-F/。你必定感受莫名其妙,这种写法哪里方便了。其实中文的数字表示就是这种形式,只不过咱们用得太习惯了,以致于没有发现。

在中文中, 代替了 /-+,而 代替了 ABC256 就写做 二百五十六个 比较累赘,咱们一般把它省略了。

其实像日语、英语用的也一样是这种记数法,简洁、优雅。

美中不足的是,这种形式虽便于读写,却不便于计算。中国古人为算筹和算盘这类经典算具搭建起广阔的舞台,却没给笔算留出一席之地。想象一下,若是让你把这些汉字写在草稿纸上,列个竖式,你的心里必定很是别扭。

位值制记数法

公元5世纪,印度数学家阿耶波多(Aryabhata 476–550)创立了如今普遍使用的 位值制记数法(positional notation/place-value notation),该记数法使用的主要符号,是同为印度人发明的阿拉伯数字:0123456789

与符值相加记数法类比,位值制中的 123 代替的是 ABC,那 /-+ 呢?是 靠阿拉伯数字的位置来表示的。众所周知,最右位至关于 /,次右位至关于 -靠每一个位置上的数值来表示数字,故名位值制。

严谨的数学家用一种多项式高度归纳了位值制记数法的本质,在十进制中,这个多项式是这样的:

这是一个 n 位十进制数,ai 就是第 i 位上的数值。为便于直观理解,举个 1024 的例子吧:

因为咱们熟悉了十进制,这样费心费力的展开可能会让你以为可笑,但当咱们把它推广到其余进制时,这个多项式的价值就体现了出来。n 位 b 进制数的位值制表示:

1024 用二进制怎么表示?

所以,1024 的二进制写做 10000000000

除了最广泛的十进制和计算机中的二进制,常见的还有七进制(如 17 天)、十二进制(如 112 个月)、十六进制(如古代 116 两)、六十进制(如六十甲子)等等,只要有意义,任何进制均可觉得你所用。

非标准位值制

在上述的多项式中,若是 ai 或 b 的取值奇葩一点,就造成了 非标准位值制(non-standard positional numeral systems),这类记数法每每应用于专业领域,很难在平常生活中见到。好比标准位值制中的三进制 ai 的取值为 012,但在一种名为平衡三进制(balanced ternary)的非标准位值制中,ai 取 -101,苏联曾使用这种进制研发电子计算机。

Part 2. 二进制简介

至此,你对「二进制」应该会感受亲切了些,它只是一种数制而已,本质上与咱们熟悉的十进制没有很大的差异,咱们这一 Part 来稍微理解一下二进制。(至于电脑为何使用二进制咱们在下一 Part 中介绍)

二进制的基本运算

十进制中的那些基本运算原则,二进制中一样适用,只不过须要稍加变幻而已,下面咱们分别就加、减、乘、除四则运算来介绍。

二级制加法

根据「逢二进一」规则,二进制数加法的法则为:

0+0=0
0+1=1+0=1
1+1=0 (进位为1) 
1+1+1=1 (进位为1)

例如:11011011 相加过程以下:

二进制数的减法

根据「借一有二」的规则,二进制数减法的法则为:

0-0=0
1-1=0
1-0=1
0-1=1 (借位为1)

例如:1101 减去 1011 的过程以下:

二进制的乘法

二进制数乘法过程可仿照十进制数乘法进行。但因为二进制数只有 01 两种可能的乘数位,致使二进制乘法更为简单。二进制数乘法的法则为:

0×0=0
0×1=1×0=0
1×1=1

例如:10011010 相乘的过程以下:

二进制的除法

二进制数除法与十进制数除法很相似。

例如:100110 ÷ 110 的过程以下:

二进制为何能表示全部的数据

由于编码规定。

以前咱们有说到,全部保存的程序和数据在计算机中都被描述为 文件,也就是说咱们可以知道当前的数据集合被指望的用途是什么,也就可以找到对应的 处理器 来正确处理当前的数据。

例如保存文字

拿文字举例,为了让一串 01 可以表明特定的文字,人们规定使用一个字节中的七位来表达特定的文字, 这就是大名鼎鼎 ASCII (American Standard Code for Information Interchange) 码,ASCll 码可以表达 27=128 种字符(编码从 0~127),对于 26 个英文字母和一些经常使用的可打印字符,这彻底足够了:

但是,世界文化是多元的,面对相似汉字这样的象形文字,ASCll码表用起来天然是捉襟见肘。

穷则思变,一个字节不行,那就两个字节,这就是大名鼎鼎的 Unicode 码,不难看出,Unicode 码有 216=65536 种表示方式,这样就足以表达一些经常使用的字符了,值得一提的是,Unicode 码算是在 ASCll 码上的一种扩充,其第 0~127 个编码字符与 ASCll 码表如出一辙。

再好比图片

这里涉及一点点物理知识,话说好久之前,牛顿经过三棱镜把白色的光分解成七种不一样颜色的光,后来又经过各类实验发现红、绿、蓝三种颜色的光是没法被分解的,所以咱们就称为红蓝绿为光的三原色。

至此人类已经知道了:能够经过组合不一样比例的红、绿、蓝三种颜色来得到各类各样的颜色,那么咱们就能够在计算机上模拟了。如今的计算机,通常使用 32 位来表示颜色,32 位平分给四个份量,也就是每一个份量 8 位。

为啥是四个颜色份量?

由于颜色模型中有一个 alpha 值,用来表示透明度,这一点咱们先不考虑。总之三种颜色,每一个使用 8 位来表示的话,咱们就可以表示 256 * 256 * 256 = 16777216 种颜色了,已经足够基础的使用了。

先来看一张图片:

这张图像的尺寸是 600px * 664px(px 是一种图片单位,中文名称为像素,你能够暂时理解为一个点)。咱们把它放大一下,以下图所示:

看见了吗?实际上,大部分图像(你拍摄的照片、你扫描的图片、你使用 iPad 画的图片等等...)都是位图文件,位图就是由像素点构成的,它就像是一个网格同样,每一个格子里面填一个颜色。(除了位图外,还有一种图是矢量图,它描述的是形状而非网格)

OK,我想你已经能理解图像是由像素点组成的了(事实上咱们的显示器也是),咱们只须要在编码中附带上一些额外的信息,例如图像有多大的尺寸、时间、做者、颜色深度、是否支持透明度之类的就可以对图像进行正确表示了。(视频能够简单理解成一张张接二连三的图片)

要让显示器正确显示图片或者视频,只须要让显示器上每一个像素显示特定的颜色就行了。

Part 3. 为何是二进制?

可为何必定是二进制呢?使用人类习惯的十进制很差吗?

理由一:物理上易于实现

计算机依靠电力工做,这也就意味着须要将数字信号映射到电信号,实现这种映射最简单的方法是:

  • 0 - 没有电(0 V)
  • 1 - 有点(5 V)

二进制在技术上最容易实现。这是由于具备两种 稳定状态 的物理器件不少,如门电路的导通与截止、电压的高与低等,而它们刚好能够对应表示 “1” 和 “0” 这两个数码。假如采用十进制,那么就要制造具备 10稳定状态 的物理电路,而这是很是困难的。

理由二:机器可靠性高

为何使用更复杂的数字系统是一个问题?

假设咱们使用三元(3 位数字)数字系统涉及计算机,若是咱们具备从 0 V5 V 的电压,那么咱们能够进行如下的映射:

  • 0 - 0 V;
  • 1 - 2.5 V;
  • 2 - 5 V;

看起来合理吧?可是,想象一下,我以 2.5 V 的电压发送了一个数字。可是因为电路中的一些噪声,我在输出端获得 2.3 V 的电压,所以将其视为 0。结果是?

有人给我发送了 1,但我将其视为 0。数据丢失但是一个很是严重的问题。

使用二进制则可靠得多,因为电压的高和低、电流的有和无等都是一种 质的变化,两种物理状态稳定、分明,所以,二进制码传输的抗干扰能力强,鉴别信息的可靠性高。

为何计算机系统必须有时钟

创建数字系统的目的是 仅在某些时间点测试开/关(二进制)值,这使电线(或其余设备)有时间更换。这就是计算机系统有时钟的缘由。

时钟会周期性地进行信号的测量,图中所示的 T1 和 T2 就是能够测量信号的时间点。

时钟利用全部这些时间点来保持同步。更快的时钟意味着每秒能够对电线进行更屡次测试,而且整个系统运行得更快。2 GHz 处理器每秒检查二进制值 20 亿次。在这些时间之间,容许值改变并稳定下来。处理器芯片速度越快,每秒能够测试的次数就越多,每秒能够作出的决策就越多。

理由三:运算规则简单

数学推导已经证实,对 N 进制数进行算术求和或求积运算,其运算规则各有 N(N+1)/2 种。如采用十进制,则 N=10,就有 55 种求和或求积的运算规则;而采用二进制,则 N=2,仅有 3 种求和或求积的运算规则,以上面提到的加法为例:

0+0=0,0+1=1 (1+0=1),1+1=10

于是能够大大简化运算器等物理器件的设计。

理由四:逻辑判断方便

采用二进制后,仅有的两个符号 “1” 和 “0” 正好能够与逻辑命题的两个值 “真” 和 “假” 相对应,可以方便地使用逻辑代数这一有力工具来分析和设计计算机的逻辑电路。

虽然在 1950 年代就造出了更加高效的三元计算机,但在效率和复杂度的取舍上,始终抵不过二进制。二进制仍然在当今世界中长期存在。

Part 4. CPU 的实际工做方式

上面咱们了解到计算机以二进制的形式运行,它们只有两种状态:开(1)和关(0),为了执行二进制计算,咱们须要采用一种特殊的电子元器件,称为 「晶体管」。暂时咱们把它理解为一种开关吧,通电就打开,没电流经过就关闭。

利用"开关"搭建逻辑电路

咱们知道,给电灯通上电,它就会亮:

因而,结合上开关,咱们就能搭建出最基础的 与门或门

与门

该电路的逻辑是:只有当 A 和 B 同时开启时,LED 灯才会亮,也就是认为输出 1,咱们能够利用电信号来简单模拟一下:

A

B

Y

0

0

0

1

0

0

0

1

0

1

1

1

或门

该电路的逻辑是:当 A 或者 B 开启时,LED 灯就会亮,也就是认为输出 1,咱们能够利用电信号来简单模拟一下:

A

B

Y

0

0

0

1

0

1

0

1

1

1

1

1

其余门

相似地,咱们能够借助更多的电子元器件来创造出基础的 7 种逻辑门电路:

这里须要特别提一下 异或门,咱们须要先知道有一种电子元器件能够利用电气特性对 输入取反,也就是说输入 1 则输出 0,输入 0 则输出 1,那么咱们就能够 简单模拟 出异或门逻辑电路(实际会更复杂些,这里仅展现出异或的意思):

A'B' 分别表示 AB 开关的反值,从图中咱们很容易知道只有当 AB 只存在一个输入 1 时,整个电路才会输出 1

利用逻辑门简单计算加法

OK,上面咱们了解到咱们可以利用 "开关" 来模拟逻辑的运算,咱们接下来试着还原一个简单的加法运算器是如何实现的:

仅需两个门,就能够完成基本的二进制加法运算。上图是利用 logic.ly 建立的半加法器,AB 至关于使咱们计算的两个数,最后一块至关因而咱们的数显芯片,它的功能是根据输入显示数字,从上到下的引脚(也就是图中输入的地方,一般咱们这样称呼)分别对应了 20=121=222=423=8 的输入,没有任何输入时显示为 0,若是 引脚 1(对应 20=1)像上图同样有输入,则显示 0 + 1 = 1

咱们来理解一下上方的电路:

  • 若是仅打开一个输入,但不一样时打开两个输入,则此处的 XOR 门(异或门)将打开,此时对应输入 引脚 1,显示 数字 1(相似于 1 + 0 和 0 + 1);
  • 若是两个输入均打开,则 AND 门(与门)将打开,此时对应输入 引脚 2,显示 数字 2(相似于 1 + 1);
  • 若是没有输入,则 AND 门和 XOR 门都保持关闭,此时显示 数字 0(相似于 0 + 0);

所以,若是两个都打开,则 XOR 保持关闭,而且 AND 门打开,得出正确的答案为 2

但这只是最基础的半加法运算器,不是太有用,由于它只能解决最简单的数学问题之一。但若是咱们把它们两个与另外一个输入链接,就会获得一个完整的加法器:

仔细思考几遍,你就会得知这个三个输入的加法器已经能够计算 3 个二进制数字的加法运算了,咱们如法炮制,能够经过链接更多的"进位"来使这个加法器可以运算更多的数,这固然也意味着这个计算链条更长。

大多数其余数学运算均可以加法完成。乘法只是重复加法,减法能够经过一些奇特的位反转来完成,而除法只是重复减法。而且,尽管全部现代计算机都具备基于硬件的解决方案以加快更复杂的操做,但从技术上讲,您可使用完整的加法器来完成所有操做。

总线和内存

如今,咱们的计算机只不过是一个计算器,它记不住任何内容也对输出没有任何操做,上述电路只是接了一个显示单元而已。

上面展现的是一个存储单元。它使用了大量的 NAND 门,而且在实际生产中,根据存储技术的不一样,它们可能会大不相同,但其功能是相同的。

您给它一些输入,并打开“写”位(Write 输入 1),它将把输入存储在单元内。这不只是一个存储单元,由于咱们还须要一种从中读取信息的方法。这是经过一个使能器完成的,该使能器是「存储器」中每一个位的“与”门的集合,全部位都与另外一个输入(即“读取”位)绑定在一块儿。写入和读取位一般也称为“设置”(set)和“启用”(enable)。

上面整个存储单元都包裹在所谓的寄存器中。这些寄存器链接到 总线,总线是围绕整个系统运行的一束电线,并链接到每一个组件。即便现代计算机也具备总线,尽管它们可能具备多个总线以提升多任务处理性能。

每一个寄存器仍有一个读写位,可是在这种设置下,输入和输出是同样的。这实际上很好。例如:若是要将 R1 的内容复制到 R2,则应打开 R1 的读取位,这会将 R1 的内容压入总线。当读取位打开时,您将打开 R2 的写入位,这会将总线内容复制到 R2 中。

寄存器也用于制做 RAM。RAM 一般布置在网格中,而且导线有两个方向:

解码器采用二进制输入并打开相应的编号线。例如,11 在二进制数中是 3,即最高的 2 位数字,所以解码器将打开最高的线路。每一个路口都有一个寄存器。全部这些都链接到中央总线以及中央写入和读取输入。只有跨寄存器的两条导线也都打开时,读和写输入才会打开,从而有效地容许您选择要从中进行读写的寄存器。一样,现代 RAM 要复杂得多,可是此设置仍然有效。

时钟,步进器和解码器

寄存器无处不在,是在 CPU 中移动数据并将信息存储在 CPU 中的基本工具。那么,是什么告诉他们移动数据的呢?

时钟是 CPU 核心中的第一个组件,它将按设置的时间间隔(以赫兹或每秒周期为单位)关闭和打开。这就是您看到的最直观的 CPU 速度指标。

时钟具备三种不一样的状态:基本时钟,使能时钟和设置时钟。基本时钟将打开半个周期,另外一半关闭。使能时钟用于打开寄存器,而且须要更长的时间才能确保数据被使能。设置时钟必须始终与使能时钟同时打开,不然可能会写入错误的数据。

时钟链接到步进器,步进器将从 1 到最大步数进行计数,并在完成后将自身重置为 1。时钟还链接到 CPU 能够写入的每一个寄存器的 AND 门:

这些 “与” 门还链接到另外一个组件的输出,即指令解码器。指令解码器接受 SET R2 TO R1 之类的指令,并将其解码为 CPU 能够理解的内容。它有本身的内部寄存器,称为“指令寄存器”,该寄存器存储了当前操做。它的精确程度取决于您正在运行的系统,可是一旦解码,它将打开正确的设置并启用正确寄存器的位,这些寄存器将根据时钟触发。

程序指令存储在 RAM(或现代系统中的 L1 高速缓存,更靠近 CPU)中。因为程序数据与其余全部变量同样都存储在寄存器中,所以能够随时对其进行操做以在程序中跳转。这就是程序经过循环和 if 语句获取结构的方式。跳转指令将指令解码器正在读取的存储器中的当前位置设置到其余位置。

一切如何配合

如今,咱们对 CPU 工做原理的有了一些基本的了解。主总线跨越整个系统,并链接到全部寄存器。完整的加法器以及其余一系列运算都打包在算术逻辑单元或 ALU 中。该 ALU 将与总线创建链接,而且还将具备本身的寄存器来存储正在操做的第二个数字。

为了执行计算,将程序数据从系统 RAM 加载到控制部分。控制部分从 RAM 中读取两个数字,将第一个数字加载到 ALU 的指令寄存器中,而后将第二个数字加载到总线上。同时,它向 ALU 发送指令代码,告知其操做方法。而后,ALU 执行全部计算,并将结果存储在另外一个寄存器中,CPU 能够从该寄存器中读取该值,而后继续该过程。

参考资料

  1. 原来,咱们是这样记数的 - https://www.jianshu.com/p/588...
  2. 二进制数的运算方法 - https://www.jianshu.com/p/560...
  3. 文字,图片,视频,音频的二进制表示 - https://blog.csdn.net/c46550/...
  4. 知乎 - 计算机只认识0和1可是怎么表示图像和影视等等众多应用的? | @kross - https://www.zhihu.com/questio...
  5. Introduction to binary numbers - https://pmihaylov.com/intro-b...
  6. What is Binary, and Why Do Computers Use It? - https://www.howtogeek.com/367...
  7. CPU 是怎样认识代码的? | 知乎 - https://www.zhihu.com/questio... | @Zign
  8. HTG Explains: How Does a CPU Actually Work? - https://www.howtogeek.com/367...

往期推荐

  1. 「MoreThanJava」当大学选择了计算机以后应该知道的
  2. 「MoreThanJava」计算机发展史—从织布机到IBM
  3. 「MoreThanJava」计算机系统概述
  4. 妈妈不再担忧我面试被Redis问得脸都绿了

  • 本文已收录至个人 Github 程序员成长系列 【More Than Java】,学习,不止 Code,欢迎 star:https://github.com/wmyskxz/MoreThanJava
  • 我的公众号 :wmyskxz,我的独立域名博客:wmyskxz.com,坚持原创输出,下方扫码关注,2020,与您共同成长!

很是感谢各位人才能 看到这里,若是以为本篇文章写得不错,以为 「我没有三颗心脏」有点东西 的话,求点赞,求关注,求分享,求留言!

创做不易,各位的支持和承认,就是我创做的最大动力,咱们下篇文章见!

相关文章
相关标签/搜索