天天看點

圖解 | 你管這破玩意叫計算機?

從燈泡到計算機的思想之旅

我和小宇早戀了,我們家住隔壁。

圖解 | 你管這破玩意叫計算機?

一、編碼與電路——信号的轉換

晚上父母會把手機沒收,但我們還想繼續聊天,又不敢發出聲音,于是我們想到了這個辦法...

圖解 | 你管這破玩意叫計算機?

我們把所有的中文都用燈泡的亮滅組合來表示,同時約定好每隔一秒讀取一次燈泡的狀态并記錄下來,這是我們的暗号。

我:亮亮滅滅亮

喜:滅亮亮滅滅

歡:亮滅亮滅亮

你:亮亮亮滅滅

這樣,我們雖然沒有了手機,依然可以日以繼日地聊天,雖然效率很低,但依然很快樂。

我和小宇就這樣在不經意間,将語言轉換成為了燈泡的亮滅組合,這個過程叫做編碼。

二、門電路——信号的關聯

我和小宇就這樣一直秘密保持着通話,直到上了大學,父母再也管不了我們用手機了。

但這麼多年的小燈泡通話,使我們總覺得事情沒那麼簡單,于是我們開始了一些新的探索。

圖解 | 你管這破玩意叫計算機?

我們增加了一個開關。此時當兩個開關同時閉合時,燈泡才會亮。

這樣兩個開關與燈泡之間,不再是之前簡單的對應關系了,而是有了邏輯。

開關的斷開與閉合分别對應着電路的斷開與連通。而小燈泡的不亮與亮,也分别對應着電路的斷開與連通。那這兩者就可以統一,不再依賴于具體的實物表現了。

圖解 | 你管這破玩意叫計算機?

還有,開關的連通與斷開,是主動的。而小燈泡的連通與斷開,是被動的,是結果。

我們把開關這裡的連通與斷開稱為輸入端,把燈泡的連通與斷開稱為輸出端,并且将整個電路都封裝在一個圖形裡,可以得到如下抽象:

圖解 | 你管這破玩意叫計算機?

我們決定把這種電路叫做門電路, 上面這個叫與門。

為了今後更為抽象的探索,我們将電路連通表示為數字 1,電路斷開表示為數字 0。

我們将這種表示方式稱為二進制。

輸入 A 輸入 B 輸出
1
圖解 | 你管這破玩意叫計算機?

慢慢地,我們發現了越來越多的玩法。

圖解 | 你管這破玩意叫計算機?

上面這種電路,我把他抽象成如下門電路形狀,叫做或門。

圖解 | 你管這破玩意叫計算機?

之後便一發不可收拾,我和小宇設計了越來越多的門電路,我們發現,隻要是我們能想到的邏輯關系,都可以設計成對應的門電路。

圖解 | 你管這破玩意叫計算機?

三、加法器——信号的計算

十進制數可以轉換成二進制數,而二進制數又可以對應到門電路的輸入端與輸出端。

于是我和小宇有了一個大膽的想法,能不能設計一個計算加法的電路呢?

我們首先從最簡單的一位二進制數相加開始:

0+0=0;0+1=1;1+0=1;1+1=10

變成一張表格如下

加數 A 加數 B 加和輸出 進位輸出

即我們需要設計出一種電路,可以達到表中的輸入與輸出效果。

經過不懈努力,終于發現這個電路可以由異或門和與門兩個門電路組成。

圖解 | 你管這破玩意叫計算機?

這個裝置實作了二進制的一位加法,但它并不完美,因為隻考慮了這兩個數的進位輸出,但沒有考慮上一位的進位,是以隻能叫半加器。

圖解 | 你管這破玩意叫計算機?

如果将前一個進位考慮進來,隻需再多一個半加器,并且拼接一個或門即可。

圖解 | 你管這破玩意叫計算機?

此時我們已經建立好了一個完美的一位加法器,并自豪地稱之為全加器。

圖解 | 你管這破玩意叫計算機?

全加器做出來之後,無論多少位的加法器就都可以做出來了,隻需将全加器逐個拼起來即可。我們嘗試做一個八位加法器。

圖解 | 你管這破玩意叫計算機?

OK,大功告成,有了加法器,理論上就可以實作任何的數學運算了。

因為我們知道乘法可以轉換成加法,除法可以轉換成減法,而減法又可以轉換成補碼的加法。現在我們可以自豪地稱這個部件為,算術邏輯單元 ALU。

圖解 | 你管這破玩意叫計算機?

四、時鐘——信号的震蕩

我和小宇都非常高興,終于用電路的方式實作了計算功能。

但慢慢的覺得沒什麼意思了,于是我們又突發奇想,設計了如下詭異的電路。

圖解 | 你管這破玩意叫計算機?

當閉合開關 A 時,整個電路聯通,開關 B 将會被吸下來,整個電路斷開,電磁鐵失去磁性,開關 B 又會彈上去,此時電路又聯通,開關 B 又被吸下來。

就這樣,開關 B 不斷地快速地在開和閉之間循環進行,而我們始終沒有去幹預這個電路,是以該電路有了自回報的特性。

由于開關 B 的來回震蕩,我們将這種電路稱為振蕩器,由于它可以産生不斷變化的電信号,就像時鐘一樣不停且規律地跑着,我們将這個裝置又稱為時鐘。它所産生的交替的電信号稱為時鐘信号。

五、RAM——儲存信号

雖然有了加法器,但是輸入的數字從哪裡來?能不能先儲存在某個地方呢?

我和小宇經過多次實驗,發明了一個非常複雜的電路:

圖解 | 你管這破玩意叫計算機?

如果輸入端為 1,改變"某控制端"信号(信号由 0 變化到 1 這個瞬間),則輸出端變為 1,之後輸出端仍然保持(存儲)着剛剛的 1。

如果輸入端為 0,改變"某控制端"信号,則輸出端變為 0,之後輸出端仍然保持(存儲)着剛剛的 0。

如果想不明白也沒關系,隻要記住這個電路的設計,實作了一位的存儲功能!我們叫它 1 位鎖存器。

圖解 | 你管這破玩意叫計算機?

然後我們把多個鎖存器組合起來,再加上一些 3-8 譯碼器,8-1 選擇器等電路,就可以實作一個能儲存 8 位二進制的存儲器,并且可以随機地讀寫它, 我們把它叫做 RAM,簡稱為記憶體。

圖解 | 你管這破玩意叫計算機?

這個元件通過再次組合,可以形成 N × M 的 RAM 陣列。比如我們可以表示一個 1024 * 8 的 RAM 陣列。

圖解 | 你管這破玩意叫計算機?

這表示存儲容量為 1024 個機關,每個機關占 8 位。

為了更友善地表示,我們規定 1024 = 1K,8 位 = 1 位元組(8 bit = 1 byte),那麼我們就可以說,這個 RAM 的存儲容量為 1K 個機關,每個機關占 1B。或者說,位址空間為 1K,存儲容量是 1KB。

此時這個 RAM 子產品已經近乎完美了,我們甚至可以單獨對其進行使用,将資料存入某個位址,将某個位址中的資料讀出。

怎麼友善人操作呢?隻需要将位址輸入、資料輸入、寫操作端分别接入一個控制台,由開關來控制這些信号的輸入是 1 還是 0 即可,然後再将資料輸出接入一些燈泡友善觀察,這樣一個單獨的可以手動操作的存儲裝置,就搞定啦。(下圖中有彩蛋~)

圖解 | 你管這破玩意叫計算機?

有了可讀寫的記憶體,我們就可以事先把幾個數字存儲記憶體中了,接下來,我們能否讓算術邏輯單元 ALU 自動地讀取這個數字,進行加法運算呢?

六、程式——自動化

我們先引入一個新的元件,10 位計數器,這裡的 Clk 就接入我們在第四部分講的時鐘信号,Clr 是清零端,具體效果下面動圖一目了然。

圖解 | 你管這破玩意叫計算機?

計數器的輸出就是 0,1,2,3,4,5,可以當作記憶體中的位址。

我們把這個計數器,以及上面講的 ALU 與 RAM 全部連在一起,嘗試實作一個可以累積求和的裝置。

我們想計算的是 1+2+3+4+5+6+7, 這個自動化的電腦是這麼運作的

1、用控制台在 RAM 的位址 0~6 處存上 1~7 這幾個數字的,在上一節已經實作了。

2、當計數器的值是 0 時,資料 1 被輸出到加法器進行計算,此時加法器 A=1,B=0,計算結果為 1,但記住鎖存器存儲的是上一次的加法器輸出 0,這次的計算結果要等下一次鎖存器遇到上升沿信号。

3、當計數器的值是 1 時, 資料 2 被輸入到加法器,此時鎖存器存儲了上一次的計算結果 1,并将這個 1 輸出給小燈泡,并同時回傳到加法器的B,是以此時加法器 A=2,B=1,計算結果為 3

4、當計數器的值是 3 時,以此類推,請看下圖

圖解 | 你管這破玩意叫計算機?

我們将累加求和這個過程自動化了!之後如果想計算累加和,隻需要用控制台事先在記憶體裡存好資料就可以了!是不是很友善?

七、程式指令

我們還想要更多的自動化!

現在這個裝置,隻能無腦地将 RAM 中的資料從頭到尾一直累加下去,無法選擇加哪個不加哪個,也無法選擇什麼時候停止。

比如我們 RAM 中的資料是這樣的。

位址(16 進制) 資料(10進制)
0x00 ...
0x01 10
0x02
0x03 20
0x04 30
0x05

我們隻想讓 RAM 藍色位址處的資料進行累加,其他地方的資料忽略,并且到 RAM 0x05 處就停止,該怎麼做呢?

我們可以再增加一個 RAM,這個 RAM 裡存放的資料,表示"指令"的含義!

我們先發明三種指令。

add:把 RAM 這個位置處的值進行累加

nop:忽略此處的值(也就是什麼都不做)

halt:停止(禁止計數器的值加一)

那麼要想達到上述功能,相應的這個指令 RAM 中的資料應該是這樣的。

注意:下面指令 RAM 的位址和上面資料 RAM 的位址之間有一一對應關系!

位址

(16 進制)

指令RAM的值 指令含義
nop 什麼都不做
add 累加
halt 停止

我們需要引入一個控制單元,放在如下位置。

圖解 | 你管這破玩意叫計算機?

遇到 nop 指令(0x00),那輸出就将鎖存器的 W 位禁止,不允許鎖存器寫操作,這樣累加結果就不會錄入。

再比如遇到輸入為 halt 指令(0x05),就将計數器的 EN 位禁止,不允許計數器 +1,這樣就達到了停止的效果。

此時再讓時鐘信号震蕩起來,就可以達到有選擇地求和過程,并且在指定位置懸停。那現在我們就讓時鐘信号震動起來,看看這個過程吧。(此處隻留關鍵元件)

圖解 | 你管這破玩意叫計算機?

這個控制單元該怎麼實作呢?我們知道,隻要給出輸入,給出輸出,任何元件都可以造出來。本文就不再展開了。

有了三個指令,我們知道了通過指令這種方式,配合各種複雜的控制器,即可實作将所有操作統統自動化。

接下來我們需要做的,就是設計控制器,以及約定好一大堆指令,使得通過這一大堆指令的排列組合,可以實作任何自動化的計算操作。

我們将設計好的一大堆指令

稱作指令集

我們将指令排列組合後可以實作的功能

稱作程式

我們将指令的排列組合這個過程

稱作程式設計

我們将排列組合這些指令的人

稱作程式員

而我們将承載這一切的裝置,叫做什麼呢?

沒錯,這個破玩意,就是

計算機

本文靈感來自一本計算機科普神作,《編碼 | 隐匿在計算機軟硬體背後的語言》,我在此向這本書緻敬。我把核心思想提取出來,寫成了低并發風格的文章,送給各位讀者。如果你對計算機對整體原理十分困惑,希望本篇文章可以讓你稍稍解惑。同時希望大家找時間可以将本書通篇閱讀,我保證你會很有收獲的。本文和本書的核心目的是讓你了解計算機的思想,實際上現在的計算機指令與資料都是放在記憶體中的,文中其他地方也都是對計算機的簡化模型,且不可出去真的和人家說計算機是個破玩意,尤其不許說這是低并發程式設計的閃客告訴你的喲~