CPU的內(nèi)部結(jié)構(gòu)
?CPU是中央處理器Central Processing Unit的縮寫,相當(dāng)于計算機(jī)的大腦,它的內(nèi)部由數(shù)百萬至數(shù)億個 「晶體管」 構(gòu)成。
?
在 「程序運行流程」 中,CPU
所負(fù)責(zé)的就是 「解釋和運行」 最終轉(zhuǎn)換成 「機(jī)器語言」 的程序內(nèi)容。
程序運行流程
CPU
和內(nèi)存是由許多晶體管組成的 「電子部件」 ,通常成為集成電路Integrated Circuit。
?從功能方面來看,
CPU
的內(nèi)部是由 「寄存器」 、 「控制器」 、 「運算器」 、 「時鐘」 等四個部分組成,各個部分之間由 「電流信號」 相互連通。?
CPU的四個組成部分
- 「寄存器」
- 用來 「緩存」 指令、數(shù)據(jù)等處理對象,可以將其看作是**「內(nèi)存的一種」**
- 根據(jù)種類的不同,一個
CPU
內(nèi)部戶有20~100
個寄存器
- 「控制器」
- 負(fù)責(zé)把 「內(nèi)存」 上的指令、數(shù)據(jù)等讀入**「寄存器」**
- 并根據(jù)指令的執(zhí)行結(jié)果來 「控制」 整個計算機(jī)
- 「運算器」
- 負(fù)責(zé)運算**「從內(nèi)存讀入寄存器的數(shù)據(jù)」**
- 「時鐘」
- 負(fù)責(zé)發(fā)出
CPU
開始計時的**「時鐘信號」**
- 負(fù)責(zé)發(fā)出
內(nèi)存
?通常所說的 「內(nèi)存」 指的是計算機(jī)的主要存儲器Main Memory,簡稱 「主存」 。
?
主存
通過 「控制芯片」 等與CPU
相連,主要負(fù)責(zé) 「存儲指令和數(shù)據(jù)」 。主存由 「可讀寫」 的元素構(gòu)成,每個字節(jié)(1字節(jié)=8位
)都帶有一個 「地址編號」 。CPU
可以通過該地址 「讀取」 主存中的指令和數(shù)據(jù),當(dāng)然也可以 「寫入」 數(shù)據(jù)。
程序運行機(jī)制
程序啟動后,根據(jù) 「時鐘信號」 , 「控制器」 會從 「內(nèi)存」 中讀取指令和數(shù)據(jù)。通過對這些指令加以解釋和運行, 「運算器」 就會對數(shù)據(jù)進(jìn)行運算, 「控制器」 根據(jù)該運算結(jié)果來控制計算機(jī)。
CPU是寄存器的集合體
CPU
的四個構(gòu)成部分中,我們只需要了解寄存器即可。這是因為, 「程序是把寄存器作為對象來描述的」 。
假設(shè),我們存在如下用匯編語言編寫的代碼。
? 「匯編語言」 采用助記符Memonic來編寫程序,每一個原本是 「電氣信號」 的 「機(jī)器語言指令」 都有有一個與其 「相對應(yīng)的助記符」 。
助記符通常為指令功能的英語單詞的縮寫。
?
匯編代碼
例如,mov
和add
分別是數(shù)據(jù)的存儲和相加的簡寫。
?「匯編語言和機(jī)器語言基本上是一一對應(yīng)的」
?
- 通常我們將 「匯編語言」 編寫的程序轉(zhuǎn)化成 「機(jī)器語言」 的過程稱為**「匯編」**
- 反之, 「機(jī)器語言」 程序轉(zhuǎn)化成 「匯編語言」 的程序的過程稱為**「反匯編」**
從上述的 「匯編代碼」 中,我們可以看出, 「機(jī)器語言級別的程序是通過寄存器來處理的」 ,也就是說, 「CPU是寄存器的集合體」 。eax
和ebp
表示的都是寄存器。并且,內(nèi)存的存儲場所 「通過地址編號來區(qū)分」 ,而寄存器的種類 「通過名字來區(qū)分」 。
CPU
處理程序的大致過程如下:
?使用 「高級語言」 編寫的程序會在 「編譯」 后轉(zhuǎn)化成 「機(jī)器語言」 ,然后再通過
CPU
內(nèi)部的寄存器來處理。?
寄存器的種類
?不同類型的
CPU
,其內(nèi)部寄存器的數(shù)量、種類以及寄存器存儲的數(shù)值范圍都是不同的。?
不過,根據(jù)功能的不同,我們可以將寄存器大致分為 「8類」 。
寄存器的主要種類和功能
可以看出,寄存器中存儲的內(nèi)容既 「可以是指令也可以是數(shù)據(jù)」 。其中,數(shù)據(jù)分為 「用于運算的數(shù)據(jù)」 和**「表示內(nèi)存地址的數(shù)據(jù)」**
CPU是寄存器的集合體
決定程序流程的程序計數(shù)器
只有1行的有用程序是很少見的,機(jī)器語言的程序也是如此。接下來,我們看一下程序是如何按照流程運行的。
下圖是程序啟動后的內(nèi)存內(nèi)容的模型。
?用戶發(fā)出啟動程序的指示后, 「操作系統(tǒng)」 會把 「硬盤」 中保存的程序 「復(fù)制」 到 「內(nèi)存」 中。
?
實例中的程序?qū)崿F(xiàn)的是將123
和456
兩個數(shù)值相加,并將結(jié)果輸出到顯示器上。
前面我們已經(jīng)介紹過,存儲指令和數(shù)據(jù)的內(nèi)存,是通過地址來劃分的。由于使用機(jī)器語言難以清晰地表明各地址存儲的內(nèi)容,因此我們對各地址的存儲內(nèi)容添加注釋。實際上, 「一個命令和數(shù)據(jù)通常被存儲在多個地址上」 ,但是為了便于說明,上面的圖例中,把指令、數(shù)據(jù)分配到一個地址中。
大致流程如下:
- 地址
0100
是程序運行的開始位置。 - 操作系統(tǒng)把程序從 「硬盤」 復(fù)制到 「內(nèi)存」 后,會將 「程序計數(shù)器」 (
CPU
寄存器的一種)設(shè)定為0100
,然后程序便開始運行。 - 「
CPU
每執(zhí)行一個指令,程序計數(shù)器的值就會自動加1」 - 然后,
CPU
的 「控制器」 就會參照程序計數(shù)器的數(shù)值,從內(nèi)存中讀取命令并執(zhí)行。
?程序計數(shù)器決定著程序的流程
?
條件分支和循環(huán)機(jī)制
程序的流程分為 「順序執(zhí)行」 、 「條件分支」 和 「循環(huán)」 三種。
- 「順序執(zhí)行」 是指按照地址內(nèi)容的順序執(zhí)行指令
- 「條件分支」 是指根據(jù)條件執(zhí)行任意地址的指令
- 「循環(huán)」 是指重復(fù)執(zhí)行同一地址的指令
「順序執(zhí)行」 的情況比較簡單,每執(zhí)行一個指令 「程序計數(shù)器」 的值就 「自動加1」 .但若程序中存在 「條件分支」 和 「循環(huán)」 ,機(jī)器語言的指令就可以將 「程序計數(shù)器」 的值設(shè)定為 「任意地址」 (不是加1)。這樣一來,程序便可以返回到上一個地址來重復(fù)執(zhí)行同一個指令,或者跳轉(zhuǎn)到任意地址。
條件分支運行流程
上圖表示把內(nèi)存中存儲的數(shù)值(示例中是123)的絕對值輸出到顯示器的程序的內(nèi)存狀態(tài)。
大致流程如下:
- 程序運行的開始位置是
0100
地址 - 隨著 「程序計數(shù)器」 數(shù)值的增加
- 當(dāng)?shù)竭_(dá)
0102
地址時,如果 「累加寄存器」 的值是 「正數(shù)」 ,則執(zhí)行 「跳轉(zhuǎn)指令」 (jump
指令)跳轉(zhuǎn)到0104
地址 - 此時,由于 「累加寄存器」 的值是
123
,為 「正數(shù)」 ,因此0103
地址的指令被跳過,程序的流程 「直接」 跳轉(zhuǎn)到了0104
地址
? 「條件分支」 和 「循環(huán)」 中使用的 「跳轉(zhuǎn)指令」 ,會參照當(dāng)前執(zhí)行的 「運算結(jié)果」 來判斷是否跳轉(zhuǎn)。
?
前面我們提到過 「標(biāo)志寄存器」 。無論當(dāng)前 「累加寄存器」 的運算結(jié)果是負(fù)數(shù)、零還是正數(shù), 「標(biāo)志寄存器」 都會將其保存。
CPU
在進(jìn)行運算時, 「標(biāo)志寄存器」 的數(shù)值會根據(jù)運算結(jié)果 「自動設(shè)定」 。至于是否執(zhí)行 「跳轉(zhuǎn)指令」 ,則由CPU
在參考 「標(biāo)志寄存器」 的數(shù)值后進(jìn)行判斷。運算結(jié)果的正、零、負(fù) 「三個狀態(tài)」 由 「標(biāo)志寄存器」 的三個位表示。
32位CPU(寄存器的長度是32位)的標(biāo)志寄存器的示例
「標(biāo)志寄存器」 的第一個字節(jié)位、第二個字節(jié)位和第三個字節(jié)位的值為1時,表示的運算結(jié)果分別為正數(shù)、零和負(fù)數(shù)。
CPU比較機(jī)制
假設(shè)要比較 「累加寄存器」 中存儲的XXX
值和 「通用寄存器」 中存儲的YYY
值,執(zhí)行比較的指令后,CPU
的運算裝置就會在內(nèi)部進(jìn)行XXX-YYY
的 「減法運行」 。
無論減法運算的結(jié)果是正數(shù)、零還是負(fù)數(shù),都會被保存到 「標(biāo)志寄存器」 中。
- 結(jié)果為 「正」 表示
XXX
比YYY
大 - 結(jié)果為 「零」 表示
XXX
和YYY
相等 - 結(jié)果為 「負(fù)」 表示
XXX
和YYY
小
?程序中的比較指令,就是在
CPU
內(nèi)部做減法運算?
函數(shù)的調(diào)用機(jī)制
?函數(shù)調(diào)用處理也是通過把 「程序計數(shù)器」 的值設(shè)定成函數(shù)的存儲地址來實現(xiàn)的
?
和 「條件分支」 、 「循環(huán)」 的機(jī)制不同,因為單純的跳轉(zhuǎn)指令無法實現(xiàn)函數(shù)的調(diào)用。
?函數(shù)的調(diào)用需要在完成函數(shù)內(nèi)部的處理后,處理流程再返回到函數(shù)調(diào)用點( 「函數(shù)調(diào)用指令的下一個地址」 )
?
上圖的示例為 變量a
和b
分別代入123
和456
后,將其賦值給參數(shù)來調(diào)用MyFunc
函數(shù)的C
語言程序。圖中的地址是將C
語言編譯成機(jī)器語言后運行時的地址。由于1行C
語言程序在編譯后通常會變成多行的機(jī)器語言,所以圖中的地址是 「離散」 的。
此外,通過 「跳轉(zhuǎn)指令」 把 「程序計數(shù)器」 的值設(shè)定為0260
也可以實現(xiàn)調(diào)用MyFunc
函數(shù)。函數(shù)的 「調(diào)用原點」 (0132
地址)和 「被調(diào)用函數(shù)」 (0260
地址)之間的數(shù)據(jù)傳遞,可以通過內(nèi)存或寄存器來實現(xiàn)。
當(dāng)函數(shù)處理進(jìn)行到最后的0354
地址時,我們應(yīng)該將 「程序計數(shù)器」 的值設(shè)定成函數(shù)調(diào)用后要執(zhí)行的0154
地址。我們通過機(jī)器語言的call
指令和return
指令能實現(xiàn)該功能。
call 指令和return 指令
?函數(shù)調(diào)用使用的是
call
指令,而不是跳轉(zhuǎn)指令。?
在將函數(shù)的入口地址設(shè)定到 「程序計數(shù)器」 之前, 「call指令」 會把調(diào)用函數(shù)后要執(zhí)行的指令地址存儲在名為 「棧」 的內(nèi)存內(nèi)。 「return 指令」 的功能是把保存在棧中的地址設(shè)定到 「程序計數(shù)器」 中。
通過地址和索引實現(xiàn)數(shù)組
?通過 「基址寄存器」 和 「變址寄存器」 可以對 「主內(nèi)存」 上特定的內(nèi)存區(qū)域進(jìn)行劃分,從而實現(xiàn)類似于數(shù)組的操作
?
- 用 「十六進(jìn)制數(shù)」 將計算機(jī)內(nèi)存上
00000000~FFFFFFFF
的地址劃分出來- 凡是該范圍的內(nèi)存區(qū)域,只要有一個32位的寄存器,即可查看全部的內(nèi)存地址
- 如果想要像數(shù)組那樣分割特定的內(nèi)存區(qū)域以達(dá)到連續(xù)查看的目的,使用兩個寄存器會更方便
?
CPU
會把 「基址寄存器」 + 「變址寄存器」 的值解釋為實際查看的內(nèi)存地址。?
「變址寄存器」 的值相當(dāng)于高級程序語言程序中數(shù)組的**「索引功能」**
-
cpu
+關(guān)注
關(guān)注
68文章
10870瀏覽量
211877 -
計算機(jī)
+關(guān)注
關(guān)注
19文章
7500瀏覽量
88019 -
晶體管
+關(guān)注
關(guān)注
77文章
9698瀏覽量
138246
發(fā)布評論請先 登錄
相關(guān)推薦
評論