1. 程式人生 > >計算機的本質

計算機的本質

理解 箭頭 電腦 早期 核心 跳轉 一個個 字節 答案

我相信很多人都聽過這句話:計算機本質上只有0、1和加法

可是0和1到底是怎麽構成面前這個花花綠綠的互聯網世界的呢?這其實是一個很重要的話題,我認為任何一個想要入行或者已經在業內但沒有認真想過這個問題的人都應該好好理解下這句話的意思。這個話題主要涉及的課程是大學裏的《計算機體系結構》,這是一個立足之本,是你在行業中遇到陌生問題,奇異問題的推理的根源。

讓我們來看看面前這個被叫做電腦的大鐵盒子,它裏面到底包含了哪些重要的東西?有點常識的人大概都能報出一些名字來,CPU,內存,硬盤,主板,顯卡,鍵鼠,顯示器等等

CPU是計算機的核心,這應該很多人都知道,但CPU到底是什麽?他能幹什麽?

答案是,基本的四則運算(我就不解釋加法如何衍生出四則運算了,這並不重要),數值比較,數據讀寫,指令跳轉。以上四類指令構成了CPU指令集的核心部分,當然CPU越來越強大的情況下,有很多新的指令出現比如MMX,但這不影響我們理解最基本的計算機模型

也許你已經註意到了他並不是只有加法而已,實際上數值比較看起來就不是用加法器實現的。更重要的是,數據讀寫?從哪讀?往哪寫?指令跳轉?什麽是指令?當提出這些問題時,你應該已經意識到了,CPU並不能獨立的運作,他至少需要一些額外的東西——即存儲,嚴格的來說,是內存——這是直接和CPU打交道的重要硬件(詞匯豐富的同學請先忘掉L1L2之類的東西)

什麽是內存?內存就是一個超大的盒子,這個盒子被分一個個的小格(被稱作一位(Bit))整整齊齊的排放著,每個格子都有一個自己的位置(叫做地址),每個盒子裏只能裝0或者1,不會是其他狀態,他們總是0或者1。只要你告訴內存一個地址,他就會告訴你對應盒子裏的數據——立刻告訴你,反應非常快,這就是為什麽他的學名叫做隨機訪問存儲器——你隨機給他一個地址,他就能瞬間訪問其中的數據。

但只有0和1實在是太不方便了——這幾乎什麽都幹不了,所以我們把連續的八個格子(八位)組合成一個整體,這樣他就能表示0-255的一個整數(參見二進制),當然表示什麽是我們說了算的,這取決於我們具體怎麽使用和解釋它——舉個例子來說,你在紙上畫了一個圈代表蘋果,你女朋友在紙上畫了一個圈代表橙子,那麽圈到底是蘋果還是橙子?這取決於是你去解釋還是你女朋友去解釋,當然如果寫的人和解釋的人不一樣,那就會出現混亂——明明你畫的時候想的是蘋果,她卻解釋成橙子,這是要出問題的,所以我們有了一些約定,或者叫數據標準

八位的數據叫做一個“字節”(Byte),一個字節可以用來表示0-255,這叫做無符號數,也可以用來表示-128-127(感謝指正),這叫做有符號數,還可以用來表示字母,數字,各種英文標點,這叫做ASCII碼——而解釋權,在於程序員,一個常見的新手題是,怎麽輸出A的下一個字母,答案是A+1,為什麽呢,因為ASCII中,字母是按順序排列的,而這個題裏,其實程序員“故意”濫用了數據標準,他獲得了一個A,但他知道A本質上只是一個內存裏的數字,所以他可以把A當做一個無符號數來做加法,回頭再把它解釋回ASCII,他就變成了B

這種“故意”的行為在程序圈還有很多,作為各種各樣的編程技巧存在,當你無法理解一個編程技巧時,那麽不妨嘗試這去想想他背後的真實實現到底是什麽樣

0-255其實也不怎麽夠用,雖然很多人應該都很熟悉255這個上限了,在早期內存緊張的時候,很多遊戲裏的數據都禁止超過255,但現在來說,255顯然不夠用了,我們的CPU一般是64位的,老一點的可能是32位,32位,就是4個字節,他可以表示一個0-大約4億的正整數——這通常都夠用了,而64位,已經遠遠超出了日常需求(除了魔獸中變態的BOSS血量)

CPU的位數實際是說他所能計算的(對,就是四則運算和比較運算)數字的上限,既然如此,自然也就是他從內存中取數據的長度——64位的CPU最多一口氣取一個64位的數據,所以很多事情我們都得一步步來做,比如比較兩個字符串“aaaaaaaaa”,"aaaaaaaaa",按剛剛說的,如果只有8個a,我們倒是可以假裝他們是一個64位整數,然後取進來比較,可是9個a就不行了,我們必須至少分兩次來做——實際上為了方便人類理解,我們通常都分9次來做,反正對電腦來說不差7次,這恐怕連1微秒都不需要

那指令跳轉又是什麽意思呢?什麽是指令呢?指令就是一條條的計算機命令,比如把2和5加起來呀,把剛剛加完的結果放到內存第8字節呀,再把3和3加起來放到第6字節呀,然後用第八字節裏的數減去第六字節裏的數,如果大於0,就消滅全人類,否則,就從頭再算一遍之類的——顯然,其中消滅全人類不是一個有效的指令,CPU指令集裏沒這條,所以電腦只能表示一臉懵逼,可是從頭再算一遍,這個是說什麽呢?

我們回來看看剛才說的那麽一大段,這其實就是一個簡單的“程序”,顯然他由一系列的指令構成,指令也是有順序的,每條指令都包含了一個指令編號,和一組參數,顯然指令編號也是一個數字——那麽整個指令,其實就是一組數字,一個程序,也就是一組數字,那麽他自然會被放到內存當中

CPU總是從一個程序的開頭開始執行指令,然後依次執行下一條——除非你使用了跳轉命令,他則會執行你指定的地方,然後執行那條命令的下一條,你可以想象CPU裏存在一個箭頭,指向當前執行的指令,每執行完一條指令,他會自動指向下一條,而跳轉命令,可以讓你手動控制這個箭頭的位置

讓我們來看看比較剛剛兩個字符串的例子吧

我們假設兩個字符串分別已經被放到了第0-8字節,和第10-18字節

那麽我們怎麽比較這倆字符串呢,你當然可以這麽寫:

比較第0和第10,如果一樣,繼續比較,否則認為不相等並結束程序

比較第1和第11,如果一樣,繼續比較,否則認為不相等並結束程序

比較第2和第12,如果一樣,繼續比較,否則認為不相等並結束程序

…………

比較第8和第18,如果一樣,認為相等並結束程序,否則認為不相等並結束程序

但你應該意識到和太麻煩了——我們寫了太多重復的事情,當然我不指望我們能自己發明這種新的寫法,但當你知道問題所在時,應該可以很快理解為什麽別人要這麽寫:

在第100格記錄0

比較第(第100格的數字)和第(第100格的數字+10),如果一樣,繼續比較,否則認為不相等並結束程序

給第100格的數字+1

如果第100個的數字等於9,認為字符串相等,並結束程序,否則,跳轉到第2條指令繼續運行

是不是簡單了很多?不管是多長的字符串,我們都可以用這麽四行來完成比較,而不像剛才需要寫9行

沒錯,這個就叫循環——新人通常最難理解的第一個關卡

先說到這裏吧,下一次再來說說外設,即剛剛我們假設內存裏已經被放好兩個字符串,那麽他們是怎麽放進來的,以及完成比較之後,我們又要做什麽才能告訴計算機面前的人,嘿,我比完了,結果是相等/不相等

計算機的本質