一篇關於 CPU 的入門知識

不管你玩硬件還是做軟件,你的世界都少不了計算機最核心的 —— CPU。

01

CPU 是什麼?

CPU 與計算機的關係就相當於大腦和人的關係,它是一種小型的計算機芯片,通常嵌入在電腦的主板上。

CPU 的構建是通過在單個計算機芯片上放置數十億個微型晶體管來實現。

這些晶體管使它能夠執行運行存儲在系統內存中的程序所需的計算,所以,也可以說 CPU 決定了你電腦的計算能力。

02

CPU 實際做什麼?

CPU 的工作核心是從程序或應用程序中獲取指令並且執行計算。

這個過程一共有三個關鍵階段:提取,解碼和執行。

CPU 先從系統的 RAM 中提取指令,隨後解碼該指令的實際內容,最後再由 CPU 的相關部分執行該指令。

03

CPU 的內部結構

剛纔提到了很多 CPU 的重要性,那麼 CPU 的內部結構是什麼呢?又是由什麼組成的呢?

下圖展示了一般程序的運行流程(以 C 語言爲例),一般來說,瞭解程序的運行流程是掌握程序運行機制的基礎和前提。

在這個流程中,CPU 負責解釋和運行最終轉換成機器語言的內容,CPU 主要由兩部分構成:控制單元和算數邏輯單元(ALU)。

CPU 和內存都是由許多晶體管組成的電子部件,可以把它比作計算機的心臟和大腦。

它能夠接收數據輸入、執行指令並且處理相關信息,它與輸入 / 輸出(I/O)設備進行通信,這些設備向 CPU 發送數據和從 CPU 接收數據。

從功能上來看,CPU 的內容是由寄存器、控制器、運算器和時鐘四部分組成的,各個部分之間通電信號來連通。

接下來簡單介紹一下內存,爲什麼說到 CPU 需要講一下內存呢?

因爲內存是與 CPU 進行溝通的橋樑,計算機中所有程序的運行都在內存中得到運行的。

內存一般又被稱爲主存,它的作用是存放 CPU 中的運算數據,以及與硬盤等外部存儲設備交換的數據。

CPU 會在計算機運轉時,把需要運算的數據調到主存中進行運算。

在運算完成之後,CPU 將結果傳送出來,主存的運行也決定了計算機的穩定運行。

主存一般通過控制芯片與 CPU 相連,由可讀寫的元素構成,每個字節都有一個地址編號。

CPU 通過地址從主存中讀取數據和指令,也可以根據地址寫入數據,注意一點:當計算機關機時,內存中的指令和數據也會被清除。

04

CPU 是寄存器的集合體

在 CPU 的四個結構中,寄存器的重要性遠遠高於其餘三個,爲什麼這麼說?因爲程序通常是把寄存器作爲對象來進行描述的。

而說到寄存器,就不得不說到彙編語言,說到彙編語言,就不得不說到高級語言,說起高級語言也就不得不提及語言的概念。

05

計算機語言

人和人之間最古老和直接的溝通媒介是語言,但是和計算機溝通,就必須按照計算機指令來交換,其中就涉及到語言的問題。

最早,爲了解決計算機和人類的交流的問題,出現了彙編語言。

但是彙編語言晦澀難懂,所以又出現了像是 C、C++、Java 的這種高級語言,因此計算機語言一般分爲低級語言和高級語言。

使用高級語言編寫的程序,經過編譯轉換成機器語言後才能運行,而彙編語言經過彙編器才能轉換爲機器語言。

06

彙編語言

我們先來看一段採用彙編語言表示的代碼清單:

這是採用彙編語言編寫程序的一部分,彙編語言採用助記符來編寫程序,每個原本是電信號的機器語言指令會有一個與其對應的助記符。

比如,mov,add 分別是數據的存儲(move)和相加(addition)的簡寫。

彙編語言和機器語言一一對應,這點和高級語言不同,我們通常把彙編語言編寫的程序轉換爲機器語言的這個過程,稱之爲彙編。

與之相反,將機器語言轉化爲彙編語言的過程稱之爲反彙編。

彙編語言可以幫助你理解計算機做了什麼工作,機器語言級別的程序通過寄存器來處理,上面代碼中的 eax,ebp 都是表示的寄存器,它們是 CPU 內部寄存器的名稱。

因此,可以說 CPU 是一系列寄存器的集合體。

一般,在內存中的存儲通過地址編號來表示,寄存器的種類是通過名字來區分。

那些不同類型的 CPU,其內部寄存器的種類、數量以及寄存器存儲的數值範圍也都是不同的。

不過,根據功能的不同,我們可以將寄存器劃分爲下面幾類:

其中,程序計數器、標誌寄存器、累加寄存器、指令寄存器和棧寄存器只有一個,其他寄存器一般有好幾個。

07

程序計數器

程序計數器是用來存儲下一條指令所在單元的地址。

程序在執行時,PC 的初值作爲程序第一條指令的地址,在順序執行程序時,控制器先按照程序計數器所指出的指令地址,從內存中取出一條指令,隨後分析和執行該指令,並同時將 PC 的值加 1 指向下一條要執行的指令。

我們可以通過一個事例來仔細看一下程序計數器的執行過程:

這是一段進行相加的操作,程序啓動,在經過編譯解析後,會經由操作系統把硬盤中的程序複製到內存中。

以上示例程序,就是將 123 和 456 執行相加的操作,隨後將結果輸出到顯示器上,因爲使用機器語言很難描述,所以這些都是經過翻譯後的結果。

事實上,每個指令和數據都有可能分佈在不同的地址上,但是爲了更好的說明,就把組成一條指令的內存和數據放在了一個內存地址上。

地址 0100 是程序運行的起始位置,Windows 等操作系統把程序從硬盤複製到內存以後,就會將程序計數器作爲設定爲起始位置 0100,然後再執行程序,每次執行一條指令後,程序計數器的數值就會增加 1,或者是直接指向下一條指令的地址。

隨後,CPU 會根據程序計數器的數值,從內存中讀取命令並且執行,換言之,程序計數器控制着程序的流程。

08

條件分支和循環機制

小夥伴們都學過高級語言,高級語言彙總的條件控制流程主要分爲順序執行、條件分支、循環判斷三種。

一般情況下,順序執行的情況較簡單,每次執行一條指令程序計數器的值就是 + 1。

條件和循環分支會使得程序計數器的值指向任意的地址,這樣一來,程序就可以返回到上一個地址來重複執行同一個指令,或者跳轉到其它任意指令。

下面,我們就以條件分支舉例來說明程序的執行過程:

程序的開始過程和順序流程是一樣的,程序的順序流程和開始過程相同。

CPU 從 0100 處就開始執行命令,在 0100 和 0101 中都是順序執行,PC 的值順序 + 1,執行到 0102 地址的指令時,判斷 0106 寄存器的數值大於 0,跳轉到 0104 地址的指令,再將數值輸到顯示器中,隨後結束程序,0103 的指令就被跳過了。

這和我們程序中的 if()判斷相同,在不滿足條件的情況下,指令一般會直接跳過。

因此,PC 的執行過程沒有直接 + 1,而是下一條指令的地址。

09

標誌寄存器

條件和循環分支會使用到 jump(跳轉指令),會根據當前的指令來判斷是否跳轉,上面我們提到了標誌寄存器,無論當前累加寄存器的運算結果是正數、負數還是零,標誌寄存器都會將其保存。

CPU 在進行運算時,標誌寄存器的數值會根據當前運算的結果自動設定,運算結果的正、負和零三種狀態由標誌寄存器的三個位表示。

標誌寄存器的第一個字節位、第二個字節位、第三個字節位各自的結果都爲 1 時,分別代表着正數、零和負數。

CPU 的執行機制比較有意思,假設累加寄存器中存儲的 XXX 和通用寄存器中存儲的 YYY 做比較,執行比較的背後,CPU 的運算機制就會做減法運算。

而無論減法運算的結果是正數、零還是負數,都會保存到標誌寄存器中。

結果爲正表示 XXX 比 YYY 大,結果爲零表示 XXX 和 YYY 相等,結果爲負表示 XXX 比 YYY 小,程序比較的指令,實際上是在 CPU 內部做減法運算。

10

函數調用機制

函數的調用和條件分支,循環機制有所不同,單純的跳轉指令無法實現函數的調用。

函數的調用需要在函數內部處理後,處理流程在返回到函數調用點(函數調用指令的下一個地址)。

函數的調用處理是通過把程序計數器的值設定成函數的存儲地址來實現的。

11

通過地址和索引實現數組

接下來是基址寄存器和變址寄存器,通過這兩個寄存器,可以對主存上的特定區域進行劃分,以此實現類似數組的操作。

首先,可以用十六進制數將計算機內存上的 00000000 - FFFFFFFF 的地址劃分出來。

這樣,凡是該範圍的內存地址,只要有一個 32 位的寄存器,就可以查看全部地址。

但是,要是想像數組那樣,分割特定的內存區域以達到連續查看的目的的話,使用兩個寄存器會更方便一些,比如,我們用兩個寄存器來表示內存的值。

這種表示方式很像數組的構造,數組是指同樣長度的數據,在內存中進行連續排列的數據構造。

用數組名錶示數組全部的值,通過索引來區分數組的各個數據元素,例如: a[0] - a[4],[] 內的 0 - 4 就是數組的下標。

12

CPU 指令執行過程

那說了這麼多,CPU 到底是怎麼一條條的執行指令的呢?幾乎全部的馮 · 諾伊曼型計算機的 CPU,工作都可以分爲 5 個階段:取指令、指令譯碼、執行指令、訪存取數、結果寫回。

取指令階段就是將內存中的指令讀取到 CPU 中寄存器的過程,程序寄存器用於存儲下一條指令所在的地址;

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/hyxWWSp4HQB4lM0CZXEMiw