1. 程式人生 > >一個程式在計算機中到底是如何執行的?

一個程式在計算機中到底是如何執行的?

在《載入記憶體,讓程式執行起來》一節中講到,程式是儲存在硬碟中的,要載入記憶體才能執行,CPU也被設計為只能從記憶體中讀取資料和指令。

對於CPU來說,記憶體僅僅是一個存放指令和資料的地方,並不能在記憶體中完成計算功能,例如要計算 a = b + c,必須將 a、b、c 都讀取到CPU內部才能進行加法運算。為了瞭解具體的運算過程,我們不妨先來看一下CPU的結構。

CPU是一個複雜的計算機部件,它內部又包含很多小零件,如下圖所示:


運算單元是CPU的大腦,負責加減乘除、比較、位移等運算工作,每種運算都有對應的電路支援,速度很快。

暫存器(Register)是CPU內部非常小、非常快速的儲存部件,它的容量很有限,對於32位的CPU,每個暫存器一般能儲存32位(4個位元組)的資料,對於64位的CPU,每個暫存器一般能儲存64位(8個位元組)的資料。為了完成各種複雜的功能,現代CPU都內建了幾十個甚至上百個的暫存器,嵌入式系統功能單一,暫存器數量較少。

我們經常聽說多少位的CPU,指的就是暫存器的的位數。現在個人電腦使用的CPU已經進入了64位時代,例如 Intel 的 Core i3、i5、i7 等。

暫存器在程式的執行過程中至關重要,不可或缺,它們可以用來完成數學運算、控制迴圈次數、控制程式的執行流程、標記CPU執行狀態等。例如,EIP(Extern Instruction Pointer )暫存器的值是下一條指令的地址,CPU執行完當前指令後,會根據 EIP 的值找到下一條指令,改變 EIP 的值,就會改變程式的執行流程;CR3 暫存器儲存著當前程序頁目錄的實體地址,切換程序就會改變 CR3 的值,這將在《

MMU部件以及對記憶體許可權的控制》中講解;EBP、ESP 暫存器用來指向棧的底部和頂部,函式呼叫會改變 EBP 和 ESP 的值,這將在《棧的概念以及棧溢位》中講解。

那麼,在CPU內部為什麼又要設定快取呢?雖然記憶體的讀取速度已經很快了,但是和CPU比起來,還是有很大差距的,不是一個數量級的,如果每次都從記憶體中讀取資料,會嚴重拖慢CPU的執行速度,CPU經常處於等待狀態,無事可做。在CPU內部設定一個快取,可以將使用頻繁的資料暫時讀取到快取,需要同一地址上的資料時,就不用大老遠地再去訪問記憶體,直接從快取中讀取即可。

大家在購買CPU時,也會經常關心快取容量,例如 Intel Core i7 3770K 的三級快取為 8MB,二級快取為 256KB,一級快取為 32KB。容量越大,CPU越強悍。

快取的容量是有限的,CPU只能從快取中讀取到部分資料,對於使用不是很頻繁的資料,會繞過快取,直接到記憶體中讀取。所以不是每次都能從快取中得到資料,這就是快取的命中率,能夠從快取中讀取就命中,否則就沒命中。關於快取的命中率又是一門學問,哪些資料保留在快取,哪些資料不保留,都有複雜的演算法。

CPU指令

要想讓CPU工作,必須藉助特定的指令,例如 add 用於加法運算,sub 用於除法運算,cmp 用於比較兩個數的大小,這稱為CPU的指令集(Instruction Set)。我們的C語言程式碼最終也會編譯成一條一條的CPU指令。不同型號的CPU支援的指令集會有所差異,但絕大部分是相同的。

我們以C語言中的加法為例來演示CPU指令的使用。假設有下面的C語言程式碼:

 

int a = 0X14, b = 0XAE, c;
c = a + b;

在VS2010 Debug模式下生成的CPU指令為:

mov  ptr[a], 0X14
mov  ptr[b], 0XAE
mov  eax, ptr[a]
add  eax, ptr[b]
mov  ptr[c], eax

mov 和 add 都是CPU指令:
1) mov 用來將一個數值移動到一個儲存位置。這個數值可以是一個常數,也可以在記憶體或者暫存器上;這個儲存位置可以是暫存器或者記憶體。

第一條指令中,ptr[a]表示變數 a 的地址,0X14是一個數值,mov ptr[a], 0X14表示把數值 0X14 移動到 ptr[a] 指向的記憶體,也就是給變數 a 賦值。第二條指令與此類似。

第三條指令中,eax是暫存器的名字,該暫存器常用在加法運算中,用來儲存某個加數或運算結果,mov eax, ptr[a]表示把變數 a 的值移動到暫存器 eax 中。

第五條指令表示把暫存器 eax 的值移動到變數 c 中,此時 exa 中的值為 a、b 相加的和。

2) add 用來將兩個數值相加,這兩個數值可以在暫存器或者記憶體中,add 會將相加的結果放在第一個數所在的位置。第四條指令add  eax, ptr[b]表示把 eax 和 ptr[a] 中的數值相加,並把結果放在 eax 中。

總起來講:第一二條指令給變數 a、b 賦值,第三四條指令完成加法運算,第五條指令將運算結果賦值給變數 c。

實際上,上面的程式碼是組合語言,不是CPU指令,組合語言還要經過簡單的轉換才能成為CPU指令;為了更加容易地說明問題,這些語句也沒有嚴格遵守彙編的語法。有興趣的同學可以自行學習組合語言,這裡不再展開講解。


本節我們講解了CPU的簡單構造以及CPU指令,重點是讓大家認識暫存器這個小而快速的儲存部件,它在程式執行過程中起著至關重要的作用,CPU就是用它來記錄程式的執行狀態,然後根據它的值再決定下一步的操作。

 

轉自:https://blog.csdn.net/czg13548930186/article/details/52629628