昨晚在回顧之前所寫的問答時,我發現一篇關於「CPU是怎麼認識代碼」的問題熱度很高,很多朋友表示看了我寫依舊雲裡霧裡,不得要領。原因在於我主要講的是編譯器的作用和CPU的工作模式,沒有涉及到更加底層的知識。大家的疑惑主要集中在一點:我們都清楚CPU只認識0和1,但CPU到底是如何認識0和1的呢?
機器是沒有思想的,只會安裝規定好的電路工作
我們在學習單片機的時候,都會將寫好的程序燒錄進CPU裡。那麼各位有沒有想過,這個過程為什麼要叫「燒錄」?
原因就是它是真的在燒:一塊晶片的內部是密密麻麻,呈矩陣排列的熔絲。當我們寫好程序後,程序經過編譯器轉換成二進位代碼(0或1),再通過燒錄器的大量流燒斷熔絲,將這些二進位代碼寫進空白的晶片。程序中的0表示這條熔絲要燒斷,1表示這條熔絲不燒,以此方法記錄二進位信息。程序燒錄好後,晶片就有了邏輯功能。
簡單來講,燒錄就是規定好了電路,用戶只需給CPU通電就行,它就可以按照事先規定好的電路得出結果。從用戶的角度來看,好像是計算機讀懂了我們寫的程序,但實際上它就是循規蹈矩,這點和我們去開燈關燈沒什麼區別,只是通斷更多,電路狀態更加複雜。
下圖是一張早期的只讀存儲器PROM,由於它在燒錄後熔絲無法恢復,所以只能用來存儲特定的程序,所以也被叫做一次性存儲器。
現在這種熔絲設計的存儲器基本上被淘汰了,取而代之的是可以反覆擦寫的EPROM,在結構上是這樣的:
我們會發現,EPROM的並沒有採用熔絲設計,而是一種像溝壑的東西,這其實是現代數字電路的基礎——場效應管。在具體介紹場效應管前,我們先來了解一下計算機的發展和集成電路。
計算機發展史和數字電路
從1946年第一臺真正意義上的電子計算機ENIAC面世至今,計算機的硬體技術已經發展到了第四代。
第一代電子管計算機:邏輯元件採用真空電子管,體積大,可靠性差,成本高昂,為日後計算機的發展奠定了基礎;第二代電晶體計算機:邏輯元件採用電晶體,電子線路的結構得以優化改善,大大提高了計算機使用壽命,減小功耗;第三代集成電路數字機:邏輯元件採用中小型規模的集成電路板,速度大幅提高,性能更強,計算機正式邁入圖像和文字處理;第四代大規模集成電路:邏輯元件採用大規模和超大規模的集成電路,性能巨幅提升,成本降低,計算機開始走進千家萬戶,也是當下我們主要使用的計算機類型。根據功能和結構的不同,集成電路可以分成三種:模擬電路,數字電路,數/模混合電路。由於模擬電路不穩定,且抗幹擾能力較差,而數/模混合還不太成熟,目前我們主要使用的集成電路板都是由數字電路搭建的。
所謂數字電路,就是用數學信號完成對數字量進程數值運算和邏輯運算的電路,其基本電學原理,都與模擬電路相同。在理解了什麼是數字電路後,我們再來看場效應管。
場效應管簡稱為MOS,是一類金屬-氧化物構成的半導體。藍色部分是場效應管的主體部分,平時處於是絕緣的,此時源級(Source)和漏級(Drain)的電流不能從中間流過。當柵極(Gate)有電壓時,一部分藍色區域變成導體,源級和漏級就被打通了。
於是我們只要通過是否給柵極電壓,就能實現電路導通與否,就好比我們去開關燈一樣。需要注意的是,場效應管看上去和模擬電路中的PN結二極體有些類似,都是實現對電流的控制,但兩者有著本質的區別:場效應管是電壓控制元件,二極體是電流控制元件,MOS不會出現擊穿情況,在安全性上要比二極體高得多。
在理解了什麼是燒錄和MOS的作用後,我們就可以設計電路,來實現算數與邏輯的運算了。
布爾運算,二進位和門電路
1845年,英國一位名不見經傳的數學家喬治·布爾在禮拜時心血來潮,認為哲學問題可以用數學來表示。他將自己的想法編成書,即《邏輯的數學分析》和《思維規律的研究》,詳細闡述了如何將邏輯問題轉換成數學公式。
布爾代數中只有兩個值:1和0;三種運算:邏輯加、邏輯乘和邏輯非。這裡的1和0並不是數字意義上的1和0,而是一個事物的兩種矛盾狀態。比如一個人,活著就是1,死了就是0。
雖然喬治·布爾的想法很有創新意義,但在當時並不受重視,甚至一度被認為是偽科學。直到喬治·布爾去世多年後,另一位計算機先驅人物,密碼學的奠基人香農發現了這份被世人遺忘的寶藏。1938年,香農在《繼電器與開關電路的符號分析》中,將布爾代數與開關電路聯繫起來,憑藉該文章,年僅22歲的香農成功取得了麻省理工電氣工程碩士學位。
人們可以依靠繼電器構成邏輯門電路,從而邏輯上的運算結果:
與門:當兩個輸入端 A、 B同時為「1」時, 輸出端 C 才為「1」 , 否則為「0」;或門:當兩個輸入端 A、 B 中, 只要至少有一個輸入端為「1」時, 輸出 端 C 就為「1非」門:輸出狀態總和輸入狀態相反。
從這三種基本的門電路,可以構成與非,異或等其他門電路,它們的符號和結構如下圖所示:
有了門電路,人類製造出了第一款電子管計算機。在設計之初,科學家們還是沿用了人類的思維採用了十進位,用十個真空管代表一位上的0~9,看起來是很方便,但一個真空管對應一位數實在是太浪費了,計算機的體積也非常大。此時另一位不世出的天才科學家又站了出來,他就是被譽為「現代計算機之父」的馮諾依曼。
馮諾依曼提出將CPU改為了二進位,二進位的好處在於它剛好與高低電平相對應,他規定1代表高電平,0代表低電平;除此之外,二進位還有一個優勢就是精度夠高,舉個例子,0~5V分成10份,電壓每變化0.5V就代表十進位0~9中的一個值,當時電子元件的遠不如現在這般精密,一旦出現誤判後果是非常嚴重的。得益於這兩點,二進位的設計一直被沿用至今。
自己設計一款CPU
嚴格來講,CPU只是晶片的一部分,不過目前我們習慣性的將這兩個概念混在一起了。CPU全稱為中央處理器,由控制單元,運算單元和存儲單元三部分組成。這裡我們單以運算器為例,來講一下如何用邏輯門來實現數的運算
運算單元的類型有很多,加法器是最基礎的一種,其餘三種運算都能用加法來實現。
在不考慮進位情況下,根據布爾代數的定義,我們可以得到加法的真值表:
其中A,B為輸入,C為進位,S為輸出值,這種加法器叫做半加器,其布爾式為A⊕B=AB+AB
當需要考慮進位時,輸入變成了三位數,根據布爾代數的定義,全加器需要多一個進位輸入,所以需要使用兩個半加器,將一個半加器的加和輸出連接到另一個半加器,這樣一來,就可以用來進位了。我們可以列出真值表,其布爾式如下:
(A⊕B)⊕C=A⊕B⊕C,由於排版原因,此處不再展開。
門電路圖如下,
當設計完全加器後,我們搭建二進位加法器了。以一個八位二進位加法器為例,則需使用八個全加器,2^8=256,所以該加法器可以進行0~255以內的加法運算,每一個全加器的進位輸入與上一個全加器的進位輸出相連。
因為減法可以看做是加負數(計算機通常採用「取反補1」),乘法看作是多個數相加,除法看作為次數是被除數的減法運算,所以我們便完成了運算器的設計。
無論是存儲器(存儲器中的0和1按照特定排序,構成不同的信息),運算器,還是控制器,他們在原理上都是一致的,都是根據布爾式推出的真值來設計出相應的門電路。所以大家現在可以理解,為什麼CPU會賣的那麼貴,在一塊小小的CPU上集成這麼多複雜的元件真的不是一件容易事。
簡單來講,一段代碼會先被編譯器翻譯,變成0和1的排列,他們對應著的高低電平,根據電平的不同走不同的邏輯電路。我們只是從鍵盤上敲了幾行代碼,計算機就要做大量的運算工作。
所以將計算機評選為人類歷史上文明程度最高的產物,真不是空穴來風。