电竞比分网-中国电竞赛事及体育赛事平台

分享

從零開始的計(jì)算機(jī)系統(tǒng),從本質(zhì)上深入理解計(jì)算機(jī)

 ccg_hz 2017-09-18

1 一切硬件的基礎(chǔ):邏輯門

邏輯門是搭建計(jì)算機(jī)的基礎(chǔ)元件,主要用于完成邏輯運(yùn)算。邏輯運(yùn)算又稱為布爾運(yùn)算,無論是輸入還是輸出,都只有0和1,用來表示兩種對立的邏輯狀態(tài)。用來執(zhí)行與、或、非這三種最基本邏輯運(yùn)算的元件稱為與門、或門、非門。使用這三種基本的邏輯門,就可以實(shí)現(xiàn)所有的邏輯運(yùn)算,進(jìn)而構(gòu)造一整套的計(jì)算。

從零開始的計(jì)算機(jī)系統(tǒng),從本質(zhì)上深入理解計(jì)算機(jī)

計(jì)算機(jī)的本質(zhì)就是上述提到的與門、或門、非門等各種門。木頭、水泵、塑料、卡子,只要能夠完成基本邏輯門的功能,任何東西都能夠做成計(jì)算機(jī)。目前除了現(xiàn)代電腦以外,市面上幾乎沒有其他計(jì)算機(jī)系統(tǒng),其實(shí)是因?yàn)槌斯I(yè)集成電路技術(shù),尚沒有別的更好的技術(shù),能夠?qū)⑸鲜鲞壿嬮T以千萬級的數(shù)量儲存在一個幾厘米見方的芯片里面,從而實(shí)現(xiàn)商業(yè)化的規(guī)模生產(chǎn)和應(yīng)用。未來隨著納米技術(shù)和分子生物技術(shù)的進(jìn)步,一定會有別的形式的商業(yè)級計(jì)算機(jī)出現(xiàn)。

2 一切運(yùn)算的基礎(chǔ):加法

或許你會懷疑上述簡單的邏輯門能夠做什么事情,接下來我們將會看到,通過組合,邏輯門就能實(shí)現(xiàn)基本的計(jì)算機(jī)功能。

與我們平常支持0到9的十進(jìn)制計(jì)算不同。因?yàn)檎麄€計(jì)算機(jī)系統(tǒng)只有0和1兩個數(shù),所以這樣的計(jì)算機(jī)系統(tǒng)只能夠支持0和1的二進(jìn)制計(jì)算,在計(jì)算機(jī)系統(tǒng)里面,所有的計(jì)算都需要轉(zhuǎn)換成二進(jìn)制。

為了實(shí)現(xiàn)上述計(jì)算功能,需要首先實(shí)現(xiàn)半加器,通過半加器實(shí)現(xiàn)全加器,再通過三個全加器的連接,就能夠形成支持上述計(jì)算的一個三位加法器了。

2.1 半加器(Half Adder)

對于給定的輸入A和B(它們都只能是0和1),通過一個或門,兩個與門,一個非門的組合,可以對兩個位進(jìn)行加法并形成進(jìn)位。

從零開始的計(jì)算機(jī)系統(tǒng),從本質(zhì)上深入理解計(jì)算機(jī)

2.2 全加器(Full Adder)

通過兩個半加器和一個或門的組合,形成一個全加器。與半加器相比,全加器在輸入上多了一個接收的進(jìn)位,可能把從低位進(jìn)位而來的數(shù)據(jù)納入到計(jì)算中,將從低位計(jì)算產(chǎn)生的進(jìn)位也加在一起。

從零開始的計(jì)算機(jī)系統(tǒng),從本質(zhì)上深入理解計(jì)算機(jī)

從零開始的計(jì)算機(jī)系統(tǒng),從本質(zhì)上深入理解計(jì)算機(jī)

2.3 三位加法器

通過三個全加器的組合,就形成了一個三位加法器。

從零開始的計(jì)算機(jī)系統(tǒng),從本質(zhì)上深入理解計(jì)算機(jī)

以此類推,為了實(shí)現(xiàn)對n位二進(jìn)制數(shù)據(jù)的加法,需要使用n個全加器芯片,并且依次把進(jìn)位傳到下一個全加器。同理,我們可以通過任意位的加法器來實(shí)現(xiàn)對于較長二進(jìn)制數(shù)的計(jì)算。盡管我們只介紹了加法運(yùn)算的實(shí)現(xiàn),實(shí)際上數(shù)學(xué)家已經(jīng)證明,加法是實(shí)現(xiàn)所有數(shù)學(xué)運(yùn)算的基礎(chǔ)。有了加法器,原則上就能通過它們搭建任何其他計(jì)算,像乘法、除法、平方、開方、三角函數(shù)、對數(shù)函數(shù)等。而偉大的計(jì)算機(jī)科學(xué)家圖靈在一百年前就已經(jīng)指明,這些簡單運(yùn)算足以支撐任何信息處理過程。

如果需要實(shí)現(xiàn)上述加法器,最直接的方法是購買相應(yīng)邏輯門級別的晶體管電子元件親自動手焊接實(shí)現(xiàn)。

隨著設(shè)計(jì)功能的復(fù)雜化,通過手動連接實(shí)現(xiàn)將會面對大量的晶體管和少量的復(fù)雜連線,因此人們發(fā)明了FPGA(Field-Programmable Gate Array),它提供了大量的基礎(chǔ)邏輯元件,這些元件封裝在一個小的芯片里面,可能看成是一個計(jì)算芯片的半成品。設(shè)計(jì)人員可以在軟件中以類似于編程的方式設(shè)計(jì)邏輯元件的連接,并將其寫入到專門的FPGA開發(fā)板中,從而實(shí)現(xiàn)相關(guān)的運(yùn)算。

3 讓計(jì)算過程自動起來:機(jī)器指令

事實(shí)上,人天生就是懶惰的,剛剛介紹的機(jī)器雖然能夠解決基本計(jì)算的問題,但是說實(shí)在的,確實(shí)非常不好用。比如現(xiàn)在需要做一個連續(xù)加的操作,假設(shè)我們希望先把三個數(shù)字加在一起,然后把另外兩個數(shù)字加在一起,最后再把另外三個數(shù)字加在一起。如果使用前面的機(jī)器,我們需要把這些數(shù)字都寫在紙上,然后按照二進(jìn)制的格式一個個地輸入進(jìn)去,并根據(jù)計(jì)算結(jié)果顯示的情況把數(shù)據(jù)抄下來,然后再進(jìn)行計(jì)算。在這個過程中,需要不斷地把數(shù)據(jù)操作過程在計(jì)算機(jī)外記錄下來,那么有沒有辦法讓計(jì)算過程自動進(jìn)行呢?答案是肯定的。

首先,我們需要一個叫做內(nèi)存的東西,它能夠把數(shù)據(jù)存儲在計(jì)算機(jī)里面,并且能夠保持一定的時間??梢园褍?nèi)存理解為一個一個的小房間,每個小房間都有一個門牌號,這就是地址,地址表示的是數(shù)據(jù)存儲的位置。內(nèi)存的主要作用就是能夠?qū)?shù)據(jù)進(jìn)行存儲、讀取和修改。關(guān)于內(nèi)存的實(shí)現(xiàn),除了上述提到的基本邏輯門的組合(組合邏輯)以外,還需要加上觸發(fā)器設(shè)計(jì)(涉及時序邏輯)實(shí)現(xiàn)。

從零開始的計(jì)算機(jī)系統(tǒng),從本質(zhì)上深入理解計(jì)算機(jī)

下圖是一個在內(nèi)存中計(jì)算求和的過程。為了表示方便,我們已經(jīng)把里面關(guān)于二進(jìn)制的表述都換成了我們較為熟悉的十進(jìn)制,實(shí)際上在計(jì)算機(jī)里面存儲的都是二進(jìn)制。在這里,每一個格子表示一個內(nèi)存地址單元,里面存放的是相應(yīng)的數(shù)據(jù),左邊是這些內(nèi)存單元的地址編號,基本上所有的地址編號都是從0開始的。

從零開始的計(jì)算機(jī)系統(tǒng),從本質(zhì)上深入理解計(jì)算機(jī)

我們需要進(jìn)行四種操作:讀取、加、保存、停止。

操作編碼
Load(讀取)10
Store(保存)11
Add(加)20
Halt(停止)99

這樣編碼只是為了方便,并沒有特別的原因。通過相應(yīng)的轉(zhuǎn)換以后,上述的相應(yīng)計(jì)算操作即可編碼成下圖所示的操作過程,存入在以1000開始的內(nèi)存地址中。

從零開始的計(jì)算機(jī)系統(tǒng),從本質(zhì)上深入理解計(jì)算機(jī)

但是,實(shí)際上這樣的編碼序列還是無法自動運(yùn)行,因?yàn)榍懊娴拿總€操作都需要指定操作數(shù)據(jù)地址,因此,假設(shè)我們規(guī)定每個操作命令加上操作數(shù)據(jù)的地址為三個內(nèi)存單元,并命名為指令,那么整個計(jì)算過程的編碼如下圖所示:

從零開始的計(jì)算機(jī)系統(tǒng),從本質(zhì)上深入理解計(jì)算機(jī)

這樣計(jì)算機(jī)就可以根據(jù)存儲在內(nèi)存中的指令一條條地往下執(zhí)行直到遇到停機(jī)指令,這樣就可以讓整個計(jì)算過程自動執(zhí)行,從而讓計(jì)算機(jī)根據(jù)寫好的指令完成我們想要的計(jì)算。

上述四個基本指令只是用于這樣的連續(xù)累加所涉及的一些操作的示意,真正通用的計(jì)算機(jī)在進(jìn)行運(yùn)算時,需要設(shè)計(jì)更多的硬件來實(shí)現(xiàn)相應(yīng)更多的指令。一個計(jì)算機(jī)系統(tǒng)支持的全部指令稱為指令集,在對計(jì)算機(jī)進(jìn)行設(shè)計(jì)時,有兩種基本的設(shè)計(jì)思路,一種是設(shè)計(jì)精簡的指令集,復(fù)雜的計(jì)算通過編程實(shí)現(xiàn)。比如可以設(shè)計(jì)只支持加減運(yùn)算的指令集,那么對于乘法的實(shí)現(xiàn),就可以通過在軟件中不斷地用加法來實(shí)現(xiàn)。這種芯片設(shè)計(jì)簡單,適用范圍廣泛。另一種是設(shè)計(jì)復(fù)雜的指令集,如直接通過硬件來實(shí)現(xiàn)乘法,可能實(shí)現(xiàn)更快的運(yùn)算速度,同時也增加了硬件設(shè)計(jì)的復(fù)雜性和成本。

在實(shí)際的硬件設(shè)計(jì)時,由于在計(jì)算過程中經(jīng)常會對一些常用的數(shù)進(jìn)行操作,于是專門設(shè)計(jì)了一種叫作寄存器的東西(如在上面的操作中,加法器計(jì)算的結(jié)果我們默認(rèn)保存在加法器,實(shí)際上一般CPU計(jì)算完的結(jié)果都保存在寄存器中),專門用于對需要中轉(zhuǎn)的數(shù)據(jù)進(jìn)行暫存,類似于平常運(yùn)算過程中用到的可擦寫的草稿紙。

Intel 8080于1974年4月發(fā)布,作為英特爾早期發(fā)布的處理器,它集成了6000只晶體管,除了上述提到的加減運(yùn)算和數(shù)據(jù)復(fù)制以外,還支持存數(shù)、取數(shù)等更多指令。這款CPU用在了1975年風(fēng)靡美國的最早的個人計(jì)算機(jī)牛郎星8800上面。在這臺機(jī)器上,操作是通過一些開關(guān)來扳動輸入的,計(jì)算的結(jié)果是通過指示燈顯示出來的。當(dāng)然在今天看來,這實(shí)在是太簡陋了,但是它的后續(xù)作品8086、80286、80386、80486等持續(xù)進(jìn)行了改進(jìn),開創(chuàng)了英特爾X86電腦系列的輝煌時代。

從零開始的計(jì)算機(jī)系統(tǒng),從本質(zhì)上深入理解計(jì)算機(jī)

4 寫點(diǎn)能讓人理解的東西:編程語言

到目前為止,通過基本的邏輯門設(shè)計(jì)和相應(yīng)的運(yùn)算指令的實(shí)現(xiàn),一臺計(jì)算機(jī)的硬件部分就已經(jīng)設(shè)計(jì)完畢了。如前所述真正的計(jì)算機(jī)在運(yùn)行的時候,是通過逐條讀取存入在內(nèi)存中的相應(yīng)指令然后進(jìn)行各種計(jì)算和操作實(shí)現(xiàn)的。類似10 0000和20 0001的被機(jī)器所識別并運(yùn)行的機(jī)器指令或操作指令,會被編碼成方便人類理解的助記形式如Load 0000和Add 0001。這就是匯編語言。

以某種假想的匯編語言為例,來看一個從1到100累加求和的計(jì)算過程。前面的數(shù)字表示語句序列,#號后面表示解釋說明。

1mov @100 ,R0# 將100存入到內(nèi)存R0單元,用于計(jì)數(shù)
2mov @0 ,A# 累加計(jì)算結(jié)果,初始值設(shè)置為0
3mov @1 ,R1# 用于增加計(jì)算
4Loop:# 表示以下部分循環(huán)執(zhí)行
5add A,R1# 將A的值和R1中的值相加后存入A
6inc R1# R1中的數(shù)增加1
7dec R0# R0中的數(shù)減少1
8jgz R0, Loop# 判斷如果R0中的值大于0,則轉(zhuǎn)到Loop處運(yùn)行
9jmp $end# 轉(zhuǎn)到End
10End# 程序結(jié)束停止,最終的計(jì)算結(jié)果存在A中

雖然這樣的程序?qū)懫饋硪呀?jīng)比直接的機(jī)器語言要方便很多,但還是不夠方便,因此需要提供高級編程語言讓用戶使用。對于上述的匯編語言實(shí)現(xiàn)的功能,現(xiàn)在絕大多數(shù)的高級編程語言(如C語言)實(shí)現(xiàn)起來應(yīng)該是這樣的:

i=1,sum=0,count-100# 計(jì)數(shù)器設(shè)為100,累加計(jì)算結(jié)果設(shè)為0
while(count-->0){# 計(jì)數(shù)器大于0的時候,計(jì)數(shù)器減1并循環(huán)執(zhí)行{}中的內(nèi)容
sum=sum+I;# 每次將sum值與i的值相加,結(jié)果存在sum中
i++;}# i的值增加1

為了在一臺計(jì)算機(jī)上實(shí)現(xiàn)上述功能,我們需要能夠?qū)崿F(xiàn)語言之間轉(zhuǎn)換的編譯器。編譯器指的是能夠?qū)⒁环N源語言翻譯成另一種目標(biāo)語言的程序。在上述計(jì)算機(jī)中,我們需要實(shí)現(xiàn)兩個編譯器,一個將高級語言編譯成匯編語言,另一個將匯編語言編譯成機(jī)器語言,如下圖所示:

從零開始的計(jì)算機(jī)系統(tǒng),從本質(zhì)上深入理解計(jì)算機(jī)

編譯器的實(shí)現(xiàn)是一個較為復(fù)雜的過程。一般首先對源語言程序進(jìn)行掃描,將其中的一些關(guān)鍵字符和存儲數(shù)據(jù)的變量進(jìn)行相應(yīng)的轉(zhuǎn)換和處理,將源語言的相應(yīng)操作對應(yīng)到目標(biāo)語言上去。在實(shí)際的編譯過程中,需要進(jìn)行多次反復(fù)處理才能夠生成最終的目標(biāo)語言。

以上面這段簡單的程序?yàn)槔?,為了?shí)現(xiàn)把這段語言轉(zhuǎn)換成匯編語言的過程,主要包括詞法分析、語法分析、語義分析、目標(biāo)代碼生成幾個階段。

4.1 詞法分析

主要是把源代碼里面所有的字符串全部讀進(jìn)來,然后進(jìn)行掃描和分解,把常量、變量名、運(yùn)算符、關(guān)鍵字等標(biāo)識出來。

4.2 語法分析

此階段主要是在詞法分析的基礎(chǔ)上將識別出來的單詞序列按照該語言的語法要素識別出相應(yīng)的語法單位。

4.3 語義分析

語義分析的主要作用是判斷整個源程序代碼里面是否有錯誤,如有C語言中對于變量是否已經(jīng)聲明、語句是否以分號結(jié)束、運(yùn)算的對象是否合理等進(jìn)行整體審查。

4.4 目標(biāo)代碼生成

將源代碼轉(zhuǎn)換成目標(biāo)代碼的過程是最重要也是最復(fù)雜的階段。如上例所示,將i=1;sum=0,count=100;語句中的三個賦值表達(dá)式轉(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)換到機(jī)器指令的基本過程也差不多,而且這個過程往往比高級語言轉(zhuǎn)換到匯編語言要簡單。因?yàn)樵谠O(shè)計(jì)CPU時,人們對于相應(yīng)的操作基本上已經(jīng)給出了相應(yīng)的操作碼。

其實(shí)對于編程語言來說,語言的關(guān)鍵字符、書寫形式等構(gòu)成的是語言的語法,但語言的強(qiáng)大與否并不在于語法,而在于提供的相應(yīng)操作函數(shù)的數(shù)量,一般語言提供的大量相關(guān)函數(shù)稱為類庫。在實(shí)現(xiàn)自己的編程語言時,除了需要實(shí)現(xiàn)語言的編譯器以外,更多的是需要提供強(qiáng)大的、適用的函數(shù)的類庫。如前面的語言,如果提供一個叫sum的累積求和函數(shù),只需要一行語句sum(1,100)就可以實(shí)現(xiàn)從1到100的加法計(jì)算功能。由于不同的語言設(shè)計(jì)目的不同,函數(shù)庫側(cè)重不同。因此不同的語言適用于不同的功能。

5 靈魂和守護(hù)者:操作系統(tǒng)

前面已經(jīng)講述了從邏輯門到編程語言的整個過程,但是不知道你有沒有注意到,從開始到現(xiàn)在,所有的例子都只提到了加減法。對于一臺真正的計(jì)算機(jī),哪怕能夠算出宇宙盡頭毀滅的時刻,對于大多數(shù)人來說,也不如能夠玩?zhèn)€植物大戰(zhàn)僵尸或者看個美國大片有用,所以,我們的計(jì)算機(jī)能夠做的可不僅僅只是算算數(shù)。

作為一套計(jì)算機(jī)系統(tǒng),除了最核心的計(jì)算單元CPU以外,還需要通過操作系統(tǒng)將其和存儲器、輸入、輸出設(shè)備連接在一起,才能夠形成完整可用的計(jì)算機(jī)系統(tǒng)。

5.1 輸出

為了使從1到100的計(jì)算結(jié)果能夠顯示在計(jì)算機(jī)屏幕上,我們需要在內(nèi)存中留出特定的區(qū)域存放用于顯示的內(nèi)容,在CPU通過指令的運(yùn)行把數(shù)據(jù)存放在特定的內(nèi)存位置上以后,操作系統(tǒng)負(fù)責(zé)不斷地將這些特定區(qū)域的內(nèi)容在屏幕上顯示出來。在這個過程中,要適應(yīng)不同的分辨率,計(jì)算在顯示器上輸出的位置。為此,操作系統(tǒng)需要適應(yīng)不同的顯示設(shè)備,根據(jù)不同的設(shè)備運(yùn)行不同的驅(qū)動程序。

5.2 輸出

同樣,操作系統(tǒng)需要接收鍵盤的輸入,在鍵盤發(fā)生了按鍵動作時,需要得到觸發(fā)的通知,將按鍵的電信號轉(zhuǎn)換為相應(yīng)的字符,并不斷將接收到的字符存在指定內(nèi)存區(qū)域,供計(jì)算機(jī)中運(yùn)行的程序使用。

在程序員進(jìn)行高級語言編程時,我們希望通過諸如printf('100')、getchar之類的命令就能夠?qū)崿F(xiàn)輸出和輸入的功能,操作系統(tǒng)負(fù)責(zé)實(shí)現(xiàn)具體的細(xì)節(jié)功能。

在簡單的計(jì)算機(jī)模型中,操作系統(tǒng)主要負(fù)責(zé)的功能有兩點(diǎn):一是封裝對于底層的硬件實(shí)現(xiàn),二是提供更多的函數(shù)支持更多的功能,如提供drawline之類的函數(shù)支持在屏幕上實(shí)現(xiàn)劃線的操作。因此,這個意義上的操作系統(tǒng)與前面提到的語言的類庫之間的界線并不是特別明顯?,F(xiàn)在主流的操作系統(tǒng)Windows、Unix和Linux,由于設(shè)置了不同程序?qū)τ谟布脑L問權(quán)限和優(yōu)先級的控制,這個界面切分得很清楚,基本上在高級語言層面是不允許直接訪問底層硬件的。

前面從如何通過基本的與、或、非邏輯門開始構(gòu)造計(jì)算機(jī)的硬件用以實(shí)現(xiàn)相應(yīng)的指令集,以及在與指令集完全對應(yīng)的機(jī)器語言上通過匯編語言進(jìn)而到高級語言來編寫計(jì)算程序,說明了構(gòu)造一臺計(jì)算機(jī)制主要過程。在整個系統(tǒng)的構(gòu)造過程中,最后一個環(huán)節(jié)就是操作系統(tǒng),操作系統(tǒng)是用來銜接計(jì)算機(jī)的硬件系統(tǒng)和軟件系統(tǒng)的,使一臺計(jì)算機(jī)對于用戶來說真正可以使用。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多