1 一切硬件的基礎:邏輯門邏輯門是搭建計算機的基礎元件,主要用于完成邏輯運算。邏輯運算又稱為布爾運算,無論是輸入還是輸出,都只有0和1,用來表示兩種對立的邏輯狀態(tài)。用來執(zhí)行與、或、非這三種最基本邏輯運算的元件稱為與門、或門、非門。使用這三種基本的邏輯門,就可以實現(xiàn)所有的邏輯運算,進而構(gòu)造一整套的計算。 計算機的本質(zhì)就是上述提到的與門、或門、非門等各種門。木頭、水泵、塑料、卡子,只要能夠完成基本邏輯門的功能,任何東西都能夠做成計算機。目前除了現(xiàn)代電腦以外,市面上幾乎沒有其他計算機系統(tǒng),其實是因為除了工業(yè)集成電路技術,尚沒有別的更好的技術,能夠?qū)⑸鲜鲞壿嬮T以千萬級的數(shù)量儲存在一個幾厘米見方的芯片里面,從而實現(xiàn)商業(yè)化的規(guī)模生產(chǎn)和應用。未來隨著納米技術和分子生物技術的進步,一定會有別的形式的商業(yè)級計算機出現(xiàn)。 2 一切運算的基礎:加法或許你會懷疑上述簡單的邏輯門能夠做什么事情,接下來我們將會看到,通過組合,邏輯門就能實現(xiàn)基本的計算機功能。 與我們平常支持0到9的十進制計算不同。因為整個計算機系統(tǒng)只有0和1兩個數(shù),所以這樣的計算機系統(tǒng)只能夠支持0和1的二進制計算,在計算機系統(tǒng)里面,所有的計算都需要轉(zhuǎn)換成二進制。 為了實現(xiàn)上述計算功能,需要首先實現(xiàn)半加器,通過半加器實現(xiàn)全加器,再通過三個全加器的連接,就能夠形成支持上述計算的一個三位加法器了。 2.1 半加器(Half Adder) 對于給定的輸入A和B(它們都只能是0和1),通過一個或門,兩個與門,一個非門的組合,可以對兩個位進行加法并形成進位。 2.2 全加器(Full Adder) 通過兩個半加器和一個或門的組合,形成一個全加器。與半加器相比,全加器在輸入上多了一個接收的進位,可能把從低位進位而來的數(shù)據(jù)納入到計算中,將從低位計算產(chǎn)生的進位也加在一起。 2.3 三位加法器 通過三個全加器的組合,就形成了一個三位加法器。 以此類推,為了實現(xiàn)對n位二進制數(shù)據(jù)的加法,需要使用n個全加器芯片,并且依次把進位傳到下一個全加器。同理,我們可以通過任意位的加法器來實現(xiàn)對于較長二進制數(shù)的計算。盡管我們只介紹了加法運算的實現(xiàn),實際上數(shù)學家已經(jīng)證明,加法是實現(xiàn)所有數(shù)學運算的基礎。有了加法器,原則上就能通過它們搭建任何其他計算,像乘法、除法、平方、開方、三角函數(shù)、對數(shù)函數(shù)等。而偉大的計算機科學家圖靈在一百年前就已經(jīng)指明,這些簡單運算足以支撐任何信息處理過程。 如果需要實現(xiàn)上述加法器,最直接的方法是購買相應邏輯門級別的晶體管電子元件親自動手焊接實現(xiàn)。 隨著設計功能的復雜化,通過手動連接實現(xiàn)將會面對大量的晶體管和少量的復雜連線,因此人們發(fā)明了FPGA(Field-Programmable Gate Array),它提供了大量的基礎邏輯元件,這些元件封裝在一個小的芯片里面,可能看成是一個計算芯片的半成品。設計人員可以在軟件中以類似于編程的方式設計邏輯元件的連接,并將其寫入到專門的FPGA開發(fā)板中,從而實現(xiàn)相關的運算。 3 讓計算過程自動起來:機器指令事實上,人天生就是懶惰的,剛剛介紹的機器雖然能夠解決基本計算的問題,但是說實在的,確實非常不好用。比如現(xiàn)在需要做一個連續(xù)加的操作,假設我們希望先把三個數(shù)字加在一起,然后把另外兩個數(shù)字加在一起,最后再把另外三個數(shù)字加在一起。如果使用前面的機器,我們需要把這些數(shù)字都寫在紙上,然后按照二進制的格式一個個地輸入進去,并根據(jù)計算結(jié)果顯示的情況把數(shù)據(jù)抄下來,然后再進行計算。在這個過程中,需要不斷地把數(shù)據(jù)操作過程在計算機外記錄下來,那么有沒有辦法讓計算過程自動進行呢?答案是肯定的。 首先,我們需要一個叫做內(nèi)存的東西,它能夠把數(shù)據(jù)存儲在計算機里面,并且能夠保持一定的時間??梢园褍?nèi)存理解為一個一個的小房間,每個小房間都有一個門牌號,這就是地址,地址表示的是數(shù)據(jù)存儲的位置。內(nèi)存的主要作用就是能夠?qū)?shù)據(jù)進行存儲、讀取和修改。關于內(nèi)存的實現(xiàn),除了上述提到的基本邏輯門的組合(組合邏輯)以外,還需要加上觸發(fā)器設計(涉及時序邏輯)實現(xiàn)。 下圖是一個在內(nèi)存中計算求和的過程。為了表示方便,我們已經(jīng)把里面關于二進制的表述都換成了我們較為熟悉的十進制,實際上在計算機里面存儲的都是二進制。在這里,每一個格子表示一個內(nèi)存地址單元,里面存放的是相應的數(shù)據(jù),左邊是這些內(nèi)存單元的地址編號,基本上所有的地址編號都是從0開始的。 我們需要進行四種操作:讀取、加、保存、停止。
這樣編碼只是為了方便,并沒有特別的原因。通過相應的轉(zhuǎn)換以后,上述的相應計算操作即可編碼成下圖所示的操作過程,存入在以1000開始的內(nèi)存地址中。 但是,實際上這樣的編碼序列還是無法自動運行,因為前面的每個操作都需要指定操作數(shù)據(jù)地址,因此,假設我們規(guī)定每個操作命令加上操作數(shù)據(jù)的地址為三個內(nèi)存單元,并命名為指令,那么整個計算過程的編碼如下圖所示: 這樣計算機就可以根據(jù)存儲在內(nèi)存中的指令一條條地往下執(zhí)行直到遇到停機指令,這樣就可以讓整個計算過程自動執(zhí)行,從而讓計算機根據(jù)寫好的指令完成我們想要的計算。 上述四個基本指令只是用于這樣的連續(xù)累加所涉及的一些操作的示意,真正通用的計算機在進行運算時,需要設計更多的硬件來實現(xiàn)相應更多的指令。一個計算機系統(tǒng)支持的全部指令稱為指令集,在對計算機進行設計時,有兩種基本的設計思路,一種是設計精簡的指令集,復雜的計算通過編程實現(xiàn)。比如可以設計只支持加減運算的指令集,那么對于乘法的實現(xiàn),就可以通過在軟件中不斷地用加法來實現(xiàn)。這種芯片設計簡單,適用范圍廣泛。另一種是設計復雜的指令集,如直接通過硬件來實現(xiàn)乘法,可能實現(xiàn)更快的運算速度,同時也增加了硬件設計的復雜性和成本。 在實際的硬件設計時,由于在計算過程中經(jīng)常會對一些常用的數(shù)進行操作,于是專門設計了一種叫作寄存器的東西(如在上面的操作中,加法器計算的結(jié)果我們默認保存在加法器,實際上一般CPU計算完的結(jié)果都保存在寄存器中),專門用于對需要中轉(zhuǎn)的數(shù)據(jù)進行暫存,類似于平常運算過程中用到的可擦寫的草稿紙。 Intel 8080于1974年4月發(fā)布,作為英特爾早期發(fā)布的處理器,它集成了6000只晶體管,除了上述提到的加減運算和數(shù)據(jù)復制以外,還支持存數(shù)、取數(shù)等更多指令。這款CPU用在了1975年風靡美國的最早的個人計算機牛郎星8800上面。在這臺機器上,操作是通過一些開關來扳動輸入的,計算的結(jié)果是通過指示燈顯示出來的。當然在今天看來,這實在是太簡陋了,但是它的后續(xù)作品8086、80286、80386、80486等持續(xù)進行了改進,開創(chuàng)了英特爾X86電腦系列的輝煌時代。 4 寫點能讓人理解的東西:編程語言到目前為止,通過基本的邏輯門設計和相應的運算指令的實現(xiàn),一臺計算機的硬件部分就已經(jīng)設計完畢了。如前所述真正的計算機在運行的時候,是通過逐條讀取存入在內(nèi)存中的相應指令然后進行各種計算和操作實現(xiàn)的。類似10 0000和20 0001的被機器所識別并運行的機器指令或操作指令,會被編碼成方便人類理解的助記形式如Load 0000和Add 0001。這就是匯編語言。 以某種假想的匯編語言為例,來看一個從1到100累加求和的計算過程。前面的數(shù)字表示語句序列,#號后面表示解釋說明。
雖然這樣的程序?qū)懫饋硪呀?jīng)比直接的機器語言要方便很多,但還是不夠方便,因此需要提供高級編程語言讓用戶使用。對于上述的匯編語言實現(xiàn)的功能,現(xiàn)在絕大多數(shù)的高級編程語言(如C語言)實現(xiàn)起來應該是這樣的:
為了在一臺計算機上實現(xiàn)上述功能,我們需要能夠?qū)崿F(xiàn)語言之間轉(zhuǎn)換的編譯器。編譯器指的是能夠?qū)⒁环N源語言翻譯成另一種目標語言的程序。在上述計算機中,我們需要實現(xiàn)兩個編譯器,一個將高級語言編譯成匯編語言,另一個將匯編語言編譯成機器語言,如下圖所示: 編譯器的實現(xiàn)是一個較為復雜的過程。一般首先對源語言程序進行掃描,將其中的一些關鍵字符和存儲數(shù)據(jù)的變量進行相應的轉(zhuǎn)換和處理,將源語言的相應操作對應到目標語言上去。在實際的編譯過程中,需要進行多次反復處理才能夠生成最終的目標語言。 以上面這段簡單的程序為例,為了實現(xiàn)把這段語言轉(zhuǎn)換成匯編語言的過程,主要包括詞法分析、語法分析、語義分析、目標代碼生成幾個階段。 4.1 詞法分析 主要是把源代碼里面所有的字符串全部讀進來,然后進行掃描和分解,把常量、變量名、運算符、關鍵字等標識出來。 4.2 語法分析 此階段主要是在詞法分析的基礎上將識別出來的單詞序列按照該語言的語法要素識別出相應的語法單位。 4.3 語義分析 語義分析的主要作用是判斷整個源程序代碼里面是否有錯誤,如有C語言中對于變量是否已經(jīng)聲明、語句是否以分號結(jié)束、運算的對象是否合理等進行整體審查。 4.4 目標代碼生成 將源代碼轉(zhuǎn)換成目標代碼的過程是最重要也是最復雜的階段。如上例所示,將i=1;sum=0,count=100;語句中的三個賦值表達式轉(zhuǎn)換成了三條Mov匯編指令,存在三個寄存器中,然后把While語句的范圍轉(zhuǎn)換成loop和end之間的代碼,sum=sum+i;轉(zhuǎn)換成add A,R1, i++轉(zhuǎn)換成inc R1, count--轉(zhuǎn)換成dec R0,而while(count-->0)則轉(zhuǎn)換成jgz R0,Loop。 從匯編語言轉(zhuǎn)換到機器指令的基本過程也差不多,而且這個過程往往比高級語言轉(zhuǎn)換到匯編語言要簡單。因為在設計CPU時,人們對于相應的操作基本上已經(jīng)給出了相應的操作碼。 其實對于編程語言來說,語言的關鍵字符、書寫形式等構(gòu)成的是語言的語法,但語言的強大與否并不在于語法,而在于提供的相應操作函數(shù)的數(shù)量,一般語言提供的大量相關函數(shù)稱為類庫。在實現(xiàn)自己的編程語言時,除了需要實現(xiàn)語言的編譯器以外,更多的是需要提供強大的、適用的函數(shù)的類庫。如前面的語言,如果提供一個叫sum的累積求和函數(shù),只需要一行語句sum(1,100)就可以實現(xiàn)從1到100的加法計算功能。由于不同的語言設計目的不同,函數(shù)庫側(cè)重不同。因此不同的語言適用于不同的功能。 5 靈魂和守護者:操作系統(tǒng)前面已經(jīng)講述了從邏輯門到編程語言的整個過程,但是不知道你有沒有注意到,從開始到現(xiàn)在,所有的例子都只提到了加減法。對于一臺真正的計算機,哪怕能夠算出宇宙盡頭毀滅的時刻,對于大多數(shù)人來說,也不如能夠玩?zhèn)€植物大戰(zhàn)僵尸或者看個美國大片有用,所以,我們的計算機能夠做的可不僅僅只是算算數(shù)。 作為一套計算機系統(tǒng),除了最核心的計算單元CPU以外,還需要通過操作系統(tǒng)將其和存儲器、輸入、輸出設備連接在一起,才能夠形成完整可用的計算機系統(tǒng)。 5.1 輸出 為了使從1到100的計算結(jié)果能夠顯示在計算機屏幕上,我們需要在內(nèi)存中留出特定的區(qū)域存放用于顯示的內(nèi)容,在CPU通過指令的運行把數(shù)據(jù)存放在特定的內(nèi)存位置上以后,操作系統(tǒng)負責不斷地將這些特定區(qū)域的內(nèi)容在屏幕上顯示出來。在這個過程中,要適應不同的分辨率,計算在顯示器上輸出的位置。為此,操作系統(tǒng)需要適應不同的顯示設備,根據(jù)不同的設備運行不同的驅(qū)動程序。 5.2 輸出 同樣,操作系統(tǒng)需要接收鍵盤的輸入,在鍵盤發(fā)生了按鍵動作時,需要得到觸發(fā)的通知,將按鍵的電信號轉(zhuǎn)換為相應的字符,并不斷將接收到的字符存在指定內(nèi)存區(qū)域,供計算機中運行的程序使用。 在程序員進行高級語言編程時,我們希望通過諸如printf('100')、getchar之類的命令就能夠?qū)崿F(xiàn)輸出和輸入的功能,操作系統(tǒng)負責實現(xiàn)具體的細節(jié)功能。 在簡單的計算機模型中,操作系統(tǒng)主要負責的功能有兩點:一是封裝對于底層的硬件實現(xiàn),二是提供更多的函數(shù)支持更多的功能,如提供drawline之類的函數(shù)支持在屏幕上實現(xiàn)劃線的操作。因此,這個意義上的操作系統(tǒng)與前面提到的語言的類庫之間的界線并不是特別明顯。現(xiàn)在主流的操作系統(tǒng)Windows、Unix和Linux,由于設置了不同程序?qū)τ谟布脑L問權限和優(yōu)先級的控制,這個界面切分得很清楚,基本上在高級語言層面是不允許直接訪問底層硬件的。 前面從如何通過基本的與、或、非邏輯門開始構(gòu)造計算機的硬件用以實現(xiàn)相應的指令集,以及在與指令集完全對應的機器語言上通過匯編語言進而到高級語言來編寫計算程序,說明了構(gòu)造一臺計算機制主要過程。在整個系統(tǒng)的構(gòu)造過程中,最后一個環(huán)節(jié)就是操作系統(tǒng),操作系統(tǒng)是用來銜接計算機的硬件系統(tǒng)和軟件系統(tǒng)的,使一臺計算機對于用戶來說真正可以使用。 |
|