計算機原理系列
歡迎大家關注「海拉魯知識大陸」 多交流不迷路
計算機原理(一)
繼續上一篇計算機原理(一)深入了解程序執行部分,進一步說說程序在馮諾依曼模型上如何執行。如果沒有了解的童鞋可以查看我上一篇文章。
1.程序的執行過程
當 CPU 執行程序的時候:
1.第一步,CPU 讀取 PC 指針指向的指令,將它導入指令寄存器。完成讀取指令這件事情有 3 個步驟:
- 步驟 1:CPU 的控制單元操作地址總線指定需要訪問的內存地址(簡單理解,就是把 PC 指針中的值拷貝到地址總線中)。
- 步驟 2:CPU 通知內存設備準備數據(內存設備準備好了,就通過數據總線將數據傳送給 CPU)。
- 步驟 3:CPU 收到內存傳來的數據后,將這個數據存入指令寄存器。
完成以上 3 步,CPU 成功讀取了 PC 指針指向指令,存入了指令寄存器。
2.然后,CPU 分析指令寄存器中的指令,確定指令的類型和參數。
3.如果是計算類型的指令,那么就交給邏輯運算單元計算;如果是存儲類型的指令,那么由控制單元執行。
4.PC 指針自增,并準備獲取下一條指令。
2.詳解a=11+15的程序執行過程
上面我們了解了基本的程序執行過程,接下來我們來看看如果用馮諾依曼模型執行a=11+15是一個怎樣的過程。
當我們寫的程序a=11+15是字符串,CPU只能執行指令。所以這里需要用到編譯器。編譯器的核心能力是翻譯,它把一種程序翻譯成CPU可執行的語言。比如java語言就是把.java轉換成.class文件類加載到JVM通過解釋器和即時編譯器(JIT Compiler)執行字節碼指令(這里大概了解下,后面我會單獨講講JVM工作原理)。
下面我們來詳細闡述a=11+15的大體執行過程:
1.編譯器通過分析,發現11和15是數據,因此編譯好的程序啟動時,會在內存中開辟出一個專門的區域存這樣的常數,這個專門用來存儲常數的區域,就是數據段,如下:
- 11 被存儲到了地址 0x100;
- 15 被存儲到了地址 0x104;
2.編譯器將a=11+15轉換成了 4 條指令,程序啟動后,這些指令被導入了一個專門用來存儲指令的區域,也就是正文段。如上圖所示,這 4 條指令被存儲到了 0x200-0x20c 的區域中:
- 0x200位置的load指令將地址0x100中的數據11導入寄存器R0;
- 0x204位置的load指令將地址0x104中的數據15導入寄存器R1;
- 0x208位置的add指令將寄存器R0和R1中的值相加,存入寄存器R2;
- 0x20c位置的store指令將寄存器R2中的值存回數據區域中的0x1108位置。
3.具體執行的時候,PC指針先指向0x200位置,然后依次執行這4條指令。
3.指令
在上面的例子中,load 指令將內存中的數據導入寄存器,我們寫成了 16 進制:0x8c000100,拆分成二進制就大體如下:
- 最左邊的6位,叫作操作碼,英文是OpCode,100011代表load指令;
- 中間的4位0000是寄存器的編號,這里代表寄存器R0;
- 后面的22位代表要讀取的地址,也就是0x100。
所以我們是把操作碼、寄存器的編號、要讀取的地址合并到了一個32位的指令中。
我們再來求加法運算的 add 指令,16進制表示是0x08048000,換算成二進制就是:
- 最左邊的6位是指令編碼,代表指令 add;
- 緊接著的4位 0000 代表寄存器 R0;
- 然后再接著的4位 0001 代表寄存器 R1;
- 再接著的4位 0010 代表寄存器 R2;
- 最后剩下的14位沒有被使用。
構造指令的過程,叫作指令的編碼,通常由編譯器完成;解析指令的過程,叫作指令的解碼,由CPU完成。由此可見CPU內部有一個循環:
- 首先CPU通過PC指針讀取對應內存地址的指令,單詞就是Fetch 。
- CPU對指令進行解碼,單詞就是Decode。
- CPU執行指令,單詞就是Execution。
- CPU將結果存回寄存器或者將寄存器存入內存,單詞就是Store。
上面4個步驟,就是CPU的指令周期。CPU的工作就是一個周期接著一個周期,周而復始。
4.指令的類型
通過上面的例子,不同類型的指令、參數個數、每個參數的位寬,都不一樣。而參數可以是以下這三種類型:
- 寄存器;
- 內存地址;
- 數值(一般是整數和浮點)。
當然,無論是寄存器、內存地址還是數值,它們都是數字。
指令從功能角度來劃分,大概有以下 5 類:
- I/O 類型的指令,比如處理和內存間數據交換的指令 store/load 等;再比如將一個內存地址的數據轉移到另一個內存地址的 mov
指令。 - 計算類型的指令,最多只能處理兩個寄存器,比如加減乘除、位運算、比較大小等。
- 跳轉類型的指令,用處就是修改 PC 指針。比如編程中大家經常會遇到需要條件判斷+跳轉的邏輯,比如if-else,swtich-case、函數調用等。
- 信號類型的指令,比如發送中斷的指令 trap。
- 閑置 CPU 的指令 nop,一般 CPU 都有這樣一條指令,執行后 CPU 會空轉一個周期。
指令還有一個分法,就是尋址模式,比如同樣是求和指令,可能會有另個版本:
- 將兩個寄存器的值相加的 add 指令。
- 將一個寄存器和一個整數相加的 addi 指令。
另外,同樣是加載內存中的數據到寄存器的 load 指令也有不同的尋址模式: - 比如直接加載一個內存地址中的數據到寄存器的指令la,叫作直接尋址。
- 直接將一個數值導入寄存器的指令li,叫作寄存器尋址。
- 將一個寄存器中的數值作為地址,然后再去加載這個地址中數據的指令lw,叫作間接尋址。
因此尋址模式是從指令如何獲取數據的角度,對指令的一種分類,目的是給編寫指令的人更多選擇。
5.指令的執行速度
CPU其實是用石英晶體產生的脈沖轉化為時鐘信號驅動的,每一次時鐘信號高低電平的轉換就是一個周期,我們叫時鐘周期。CPU的主頻,說的就是時鐘信號的頻率。比如一個1GHz的CPU,說的是時鐘信號的頻率是1G。這就是我們買電腦熟悉的需要知道CPU的頻率參數了,頻率越高性能越好了。
這里再說明一下,不是每個時鐘周期都可以執行一條指令。多數指令可能不在一個時鐘周期完成,通常需要 2 個、4 個、6 個時鐘周期。