主頁 > 軟體設計 > 簡單!代碼原來是這樣被CPU跑起來的

簡單!代碼原來是這樣被CPU跑起來的

2021-10-26 08:37:48 軟體設計

CPU對我們來說既熟悉又陌生,熟悉的是我們知道代碼是被CPU執行的,當我們的線上服務出現問題時可能首先會查看CPU負載情況,陌生的是我們并不知道CPU是如何執行代碼的,它對我們的代碼做了什么,本文意在簡單解釋我們代碼的生命周期,以及代碼是如何在CPU上跑起來的,

編譯-讓計算機認識我

一個漂亮 control+c 加上一個漂亮的 control+v,啪~,我們愉快的寫下了代碼,當代碼被保存后,它就被存在我們磁盤的某個地方,它可能是像java或者python這些高級語言寫的,也可能是像c這種古老語言寫的,但是現在它肯定沒法被運行,因為計算機不認識它們,計算機只認識0、1這樣的二進制,簡稱機器碼,那為什么我們不直接寫機器碼?如果你有這樣的思考,我只能呵呵了,請你幫我翻譯下以下機器碼:

001010100101001001001
100100101000101010101

很明顯作為高質量人類的我們也無法識別出這段代碼寫的是什么,于是出現類似java這樣的高級語言,它們給機器碼穿上了一層外衣,然后交給偉大的程式員來創造未來,

所以反過來我們的代碼需要被替換成機器碼,這樣才能被計算機認識,計算機才能幫我們干事,這個轉換的程序我們通常叫編譯

#include <studio.h>
int main() 
{
   printf("Hello World\n");
   return 0;
}

這是一段應該每個程式員都寫過的代碼(hello.c),在Linux下,當我們使用GCC來編譯Hello World程式時,只需要最簡單的命令:

gcc hello.c
./hello
# Hello World

看似很簡單的一行,但是其實編譯的程序很復雜,并不是我們想象中的編譯,真實是分為4個步驟,分別是預處理(Prepressing)、編譯(Compliation)、匯編(Assertmbly)和鏈接(Linking),

  1. 預編譯:這個程序主要是處理源代碼中以“#”開始的預編譯指令,比如“#include”、“define”等,

  2. 編譯:這個程序就是把預處理完的檔案進行詞法分析、語法分析、語意分析及優化后生產成相應的匯編代碼,這個程序是最復雜的,

  3. 匯編:這個程序就是將匯編代碼轉換成機器碼,也就是上圖的目標檔案hello.o

  4. 鏈接:我們的代碼程式經常是由多個代碼檔案組成的,當每個檔案都被匯編成“.o”檔案時,需要一套機制將它們組裝在一起,這個程序就叫做鏈接,

好吧,原來編譯是這么回事,通過這一整套的編譯操作,我們代碼終于能執行了,我們簡簡單單的運行./hello.out即可輸出Hello World,等等,這個簡簡單單的程序發生了什么?

連接-中轉站和高速公路

ok,ok,通過編譯,我們的程式終于能執行了,接下來讓我們站在CPU的視角來看看Hello World是如何被列印出來的,

首先編譯好的檔案是存在磁盤上的,得先加載到記憶體中,這里你可能會問:為什么CPU不能直接讀取磁盤的程式運行而要經過記憶體?答案是慢,緩慢的磁盤會影響我們程式執行的速度,因此需要更加快速、離CPU更近的存盤,那就是記憶體,

記憶體是一大塊存盤空間,可以存盤很多資料資訊,那么如何找到我們要寫的程式呢?答案是地址,其實每個位元組在記憶體中都有一個地址,這樣當CPU去記憶體中讀我們的程式時,只需要根據對應的地址就可以知道我們程式的具體內容,

等等...,這里似乎又有個問題,CPU是如何與我們的記憶體、磁盤通信的?應該有個媒介之類的吧,沒錯,這個媒介就是主板上的總線芯片組,總線好理解,就像高速公路,資料資訊可以通過這條高速公路傳遞到CPU中,這個芯片組是個什么玩意?電腦主板上芯片很多,這里說的主要是南橋芯片和北橋芯片,先來個解釋:

  1. 北橋芯片:北橋負責高速設備和CPU之間的溝通,主要就是CPU和記憶體、顯卡之間的通信,但是隨著技術的迭代,主板上的北橋芯片已經被內置到了CPU里了,

  2. 南橋芯片:南橋負責低速設備和北橋之間的通信,主要負責I/O總線之間的通信,如USB、LAN、ATA、SATA、音頻控制器、鍵盤控制器、實時時鐘控制器、高級電源管理等,

嗯... 為什么CPU與高速設備、低速設備之間的通信需要這兩個芯片?CPU自己不能干嗎?這里還是類似拆分任務的功能,如果把所有的任務都交給CPU來處理,CPU會太忙了,還有比較重要的一點,如果南橋芯片壞了,那么我們可以直接更換南橋,而不用換掉整個CPU,

終于CPU通過總線和芯片打通了磁盤、記憶體之間的通信了,接下來的一切開始交給CPU,

CPU-最強大腦

CPU全稱是Central Processing Unit,即中央處理單元,它的本質就是一塊超大規模的集成電路,從邏輯上來分,它的內部是由暫存器、控制器、運算器和時鐘組成的,下面來解釋下各個組成是干什么的,

  • 暫存器:CPU內部其實有很多型別的暫存器,我們只需了解暫存器就是暫存資料、指令等資訊的,它的本質是臨時存盤,由于是直接集成在CPU內部,所以讀寫它們的速度很快,一般一個CPU內部會有20-100個暫存器,這里給大家列舉下常用暫存器與其功能,

    1. 累加暫存器:存盤執行運算的資料和運算后的資料

    2. 標志暫存器:存盤運算處理后的CPU的狀態

    3. 程式計數器:存盤下一條指令所在記憶體的地址

    4. 基址暫存器:存盤資料記憶體的起始地址

    5. 變址暫存器:存盤基址暫存器的相對地址

    6. 通用暫存器:存盤任意資料

    7. 指令暫存器:存盤指令,CPU內部使用,程式員無法通程序式對該暫存器進行讀寫操作

    8. 堆疊暫存器:存盤堆疊區域的起始地址

  • 控制器:控制器負責把資料讀出或者寫入暫存器,并根據指令的結果來控制計算機,

  • 運算器:從名字就可以猜出來,運算器的主要作業就是運算,運算從記憶體讀入暫存器的值

  • 時鐘:它并不是我們見的鐘表概念,它代表了你的CPU的作業頻率,頻率越高說明你的CPU處理的速度越快,但是越快就會帶來另一個問題:散熱,

綜上所述,CPU的大致作業流程如下:在時鐘信號到來的時候,就開始作業,通過控制器把記憶體的資料讀到各個暫存器中,然后如果有計算相關的邏輯,就交給運算器,發現沒有,CPU的作業其實挺簡單的,本質就是不停的讀指令、執行指令,但是CPU是如何讀到我們的代碼指令的,以及我們的代碼里面的if else、函式呼叫都是如何執行分支判斷、函式跳轉的,我們來看個例子:

a = 1 #0x0010
b = 2 #0x0011
if a > b { #0x0012
 printf("%s","a") #0x0013
} else { 
 add(a,b) #0x0014
} 
printf("%s","end") #0x0017

func add(int a,int b) { #0x0020
  return a+b
}

這是段非常簡單的偽代碼,有分支判斷、有函式跳轉,我們來從CPU的角度看看它是如何執行的:

  1. 首先每段程式都有個開始的地址0x0010,也就是CPU讀取程式的入口

  2. 把a=1這個數字讀入通用暫存器中,程式計數器(PC暫存器)自動加1,即指向下一條指令 0x0011

  3. 指令暫存器拿到程式計數器的指令地址,把b=2這個數字讀入通用暫存器中,程式計數器(PC暫存器)自動加1,即指向下一條指令0x0012

  4. 指令暫存器發現此處是比較邏輯,會執行a-b,此時可能會有三個結果分別是大于0,等于0,小于0,然后把這個結果存到標志暫存器里,這里有個小知識,我們經常說的是CPU是64位或者32位,其實也表示了標志暫存器的長度

  1. 很明顯,a是小于b的,CPU根據標志暫存器的狀態值應該跳轉到else里面,注意這時程式計數器的值不是加1,而是設定成else的地址 0x0014,當執行到0x0015的時候,需要發生函式跳轉,程式計數器會被設定成 0x0020,但是這里并不是簡單的函式跳轉(專業術語叫做call),因為在函式執行完畢之后,還要回傳,也就是程式計數器需要從0x0020再變成0x0017,call執行的時候會把后續要執行的指令地址0x0017存到堆疊中,

  2. 當我們的add函式執行完畢之后,會有個return,return的時候會把上一步驟存入堆疊中的地址0x0017寫入程式計數器中

  3. 指令暫存器根據程式計數器當前的地址執行最后的列印(end),結束,

順序執行的指令代碼,程式計數器會自動累加(當然不一定累加的是1),然后找到下一條要執行的指令,

分支判斷的時候,程式計數器不是簡單的累加地址,需要地址的跳轉,

函式呼叫不僅僅需要跳轉地址,還要把函式執行完畢之后要執行的地址存下來,方便折回繼續執行,

其實還有個回圈執行,也就是我們代碼中的for、while之類的,這時程式計數器會不停的在某些地址之間來回切換,

最后,微信搜【假裝懂編程】,與作者零距離交流,一起學習,一起牛逼,

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/336290.html

標籤:其他

上一篇:位元組大佬的百萬級”MySQL筆記,基礎 + 優化 + 架構一鍵搞定

下一篇:畢業生就業須知

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more