網友 r00nk 寫的一篇文章(分 8 節),還專門建了一個網站。他為什麼會寫這個?因為他之前在 Reddit 上看到一個帖子,有人問“計算機實際上是如何工作的?比如,它如何傳送、閱讀、展示資料”。他之前的回答是最佳回覆,後來繼續補充豐富內容了,便有了下文。
二進位制
讓我們馬上進入資料的夢幻王國。
五的符號是什麼?5
十的符號是什麼?10
等等,這不是符號“1和0”嗎?
是的,在我們的編碼系統中,當我們要表示”十”的時候,我們會寫1和0。這裡沒有單獨表示十的符號,我們簡單地迴圈利用已有的一些符號(0~9)。所以我們把這樣的編碼系統叫做“base-ten”或者“decimal”(十進位制)。
“1和0”,“真和假”,“開或關”這些東西你可能已經聽過,它們指的都是一個不同的編碼系統。在我們的十進位制系統中,我們寫“10”來表示十,但是在binary(二進位制)中,我們寫“10”來表示二。在二進位制中沒有單獨表示二的符號,正像十進位制中沒有單獨表示十的符號一樣。“開”或“關”在二進位制中就是指“1”或“0”。
為保證你已經理解了二進位制,試著點選下面的二進位制計數器:
(原圖可互動,在原文可檢視。)
與非
現在來講些完全不同,但是相關的東西。
在計算機理論中有個叫“邏輯閘”的東西,它是個有兩個輸入和一個輸出的器件,只接收“開”或“關”這樣的輸入,輸出也是,“開”或“關”。你可能已經看出它和二進位制的關係。
一個邏輯閘的輸出是基於它的輸入的。一個邏輯閘的例項是NAND gate(與非門),試著點選左邊的開關:
(原圖可互動,在原文可檢視。)
當與非門的兩個輸入都是“開”的時候,輸出是“關”;其他情況輸出都是“開”。
還有一些更多種類的邏輯閘,不過我們現在只需要關心與非門。如果你想看看與非門在現實中什麼樣子,點這裡。
記憶體
想知道計算機怎麼儲存資料嗎?
下面這個器件叫“D型鎖存器”(D-Lauch),它儲存1個二進位制位。
(原圖可互動,在原文可檢視。)
上面的開關是要儲存的值(0 或 1),底下的開關控制這個器件是否儲存。
八個這樣的器件就可以用來在儲存器中儲存一個位元組了。
更多邏輯閘
在我們可以繼續之前,我需要給你看看更多的邏輯閘。
(原圖可互動,在原文可檢視。)
加法器
但是我們可以拿這些儲存的數字做什麼呢?
我們可以給它們做數學運算。
下面的器件叫做加法器(adder),它可以把兩個位加起來。
(原圖可互動,在原文可檢視。)
在十進位制中,如果要計算5+5,你就要追加一個1來生成10。當我們在二進位制中計算1+1時,相同的事情就發生了,我們需要追加(輸出)一個二進位制1。
如果我們有多個位需要相加,我們可以把一個加法器的追加輸入與另一個加法器的追加輸入相連,這樣來組合起這些器件。
編碼
酷~我們現在有一個基本的計算器了。我們怎麼樣才能最大程度的發揮它並組成一臺計算機呢?
編碼。
現在你知道了資料是什麼。編碼也很好解釋,它就是資料。至於為什麼它和其他的資料不同,當然是因為CPU把它解釋為指令。
比如我們想讓這個計算機做數學運算,我們可以使用像下面的系統:
指令 | 編碼 | |
“一個數加上另一個數” | 00000001 | |
“一個數減去另一個數” | 00000010 |
有了它,我們可以根據資料的形式安排邏輯閘來怎麼使用。
現在,真的很快,記憶體在計算機中由記憶體地址組織起來,這樣就允許CPU在確切的位置來請求記憶體。一般來說地址大小以位元組為單位,即8位。所以如果我們想要存取第5個記憶體位置或諸如此類,我們需要把它存為“00000101”。
回過頭來加入更多的指令到我們的表中:
“移動這個資料到其他位置” | 00000011 |
酷。現在我們可以實現這樣的東西:
“將第5個記憶體中的數和第7個記憶體中的數加起來”
把它分解:
(add) (memory address #5) (memory address #7)
實際上就是:
00000001 00000101 00000111
很可愛是吧?
指令指標
但是CPU怎麼知道去哪裡取指令呢?
在CPU中,有一小塊儲存。它可以做各種各樣的事,比如可以儲存某個叫“指令指標暫存器”的東西。指令指標暫存器儲存下一個指令的地址,並且可以在每一個指令結束後自增。所以,CPU讀取指令指標暫存器,取出下一個地址,執行它,指令指標暫存器自增,然後回到第一步。
指令指標暫存器的值可以存到一個專門的儲存單元中。你有沒有想過計算機中的一個無限迴圈是怎樣的?就是當一個指令指標暫存器指向的指令讓這個指令指標暫存器再次指向同一個指令的時候。
CPU
這是一個相對簡單的可以給你玩玩的CPU:
(原圖可互動,在原文可檢視。)
如果要修改記憶體,在CPU開關關著的時候點選相應位即可。你也可以滾動檢視記憶體。如果要讓CPU開始執行指令的話,就開啟開關。
這個CPU有3個不同的指令
指令 | 編碼 | |
指令指標暫存器指向地址的下一位地址的數加上下下一位地址的數 | 00000001 | |
指令指標暫存器指向地址的下下一位地址的數減去下一位地址的數 | 00000010 | |
指令指標暫存器指向地址的下一位地址的數移動到其下下一位地址 | 00000011 |
所有的指令都有3個位元組(包括運算元)。這意味著在每一個指令結束後指令指標暫存器將增加3。
這個指令指標暫存器可以通過儲存地址00000000訪問。