cxuan本身的 Github 很是硬核,求各位大佬 star: github.com/crisxuan/be…git
彙編代碼是計算機的一種低級表示,它是一種低級語言,能夠從字面角度去理解它,包括處理數據、管理內存、讀寫存儲設備上的數據,以及利用網絡通訊等。編譯器生成機器碼通過了一系列的轉換,這些轉換遵循編程語言
、目標機器的指令集
和操做系統
。程序員
指令集就是指揮計算機工做的指令,由於程序就是按照必定執行順序排列的指令。由於計算機的執行控制權由 CPU 操做,因此指令集就是 CPU 中用來計算和控制計算機的一系列指令的集合。每一個 CPU 在產出時都規定了與硬件電路相互配合工做的指令集。github
指令集有很多分類,可是通常分爲兩種,一種是精簡指令集
,一種是複雜指令集
。具體描述以下編程
精簡指令的英文是 reduced instruction set computer, RISC
,原意是精簡指令集計算,簡稱爲精簡指令集,是 CPU 的一種 設計模式
,能夠把 CPU 想象成一家流水線工廠,對指令數目
和尋址方式
都作了精簡,使其實現更容易,指令並行執行程度更好,編譯器的效率更高。設計模式
常見的精簡指令集處理器包括 ARM、AVR、MIPS、PARISC、RISC-V 和 SPARC。數組
因此你就能理解緩存
這本書是講啥的了。安全
它主要是基於 MIPS 體系結構把馮諾依曼體系的五大組件進行了逐一的硬件實現 + 軟件設計介紹,更爲重要的是引入了諸多並行計算的內容,這是大部分教材中忽略或者內容較少的,會根據這個思路把並行相關的內容,結合 OpenMP, CUDA 和 Hadoop/Spark 總體融入到新書中,畢竟這是將來發展的趨勢markdown
還有這本書網絡
這本書又是講啥的。
這本書是講 RISC-V 指令集的,由於指令集的不一樣也區分了三個版本,三個版本???嗯,還有下面這個
這本書是講 ARM 指令集的。
因此通常在看 CASPP 的時候併發的看看這本書是很是不錯的選擇。
精簡指令集通常具備以下特徵
複雜指令集的英文是 Complex Instruction Set Computing, CISC
,是一種微處理器指令集架構,也被譯爲複雜指令集。
複雜指令集包括 System/360、VAX、x86 等。
複雜指令集能夠說是在精簡指令集之上做出的改變。
複雜指令集的特色是指令數目多而複雜,每條指令字長並不相等,計算機必須加以判讀,併爲此付出了性能的代價。
通常來講,提高 CPU 性能的方法有以下這幾種
比較抽象,咱們後面會組織成文章具體介紹一下。
C 編譯器會接收其餘操做並把其轉換爲彙編語言
輸出,彙編語言是機器級別的代碼表示。咱們以前介紹過,C 語言程序的執行過程分爲下面這幾步
下面咱們更多的討論都是基於彙編代碼來討論。
咱們平常所接觸的高級語言,都是通過了層層封裝的結果,因此咱們日常是接觸不到彙編語言的,更不會用匯編語言來進行編程,這就和你不知道操做系統的存在同樣,但其實你每一個操做,甚至你雙擊一個圖標都和操做系統有關係。
高級語言的抽象級別很高,可是通過了層層抽象以後,高級語言的執行效率確定沒有彙編語言高,也沒有彙編語言可靠。
可是高級語言有更大的優勢是其編譯後可以在不一樣的機器上運行,彙編語言針對不一樣的指令集有不一樣的表示。而且高級語言學習來更加通俗易懂,下降計算機門檻,讓內卷更加嚴重(固然這是開個玩笑,冒犯到請別當真)。
話很少說,瞭解底層必須瞭解彙編語言。不然一個 synchronized 底層實現就可以讓你頭疼不已。並且,每天飄着也很差,早晚要落地。
瞭解彙編代碼也有助於咱們優化程序代碼,分析代碼中隱含的低效率,而且這種優化方法一旦優化成功,將是量級的提升,而不是改改 if...else ,使用一個新特性所能比的。
計算機系統使用了多種不一樣形式的抽象,能夠經過一個簡單的抽象模型來隱藏實現細節。對於機器級別的程序來講,有兩點很是重要。
首先第一點,定義機器級別程序的格式和行爲被稱爲 指令集體系結構或指令集架構(instruction set architecture)
, ISA。ISA 定義了進程狀態、指令的格式和每個指令對狀態的影響。大部分的指令集架構包括 ISA 用來描述進程的行爲就好像是順序執行的,一條指令執行結束後,另一條指令再開始。處理器硬件的描述要更復雜,它能夠同時並行執行許多指令,可是它採用了安全措施
來確保總體行爲與 ISA 規定的順序一致。
第二點,機器級別對內存地址的描述就是 虛擬地址(virtual address)
,它提供了一個內存模型來表示一個巨大的字節數組。
編譯器在整個編譯的過程當中起到了相當重要的做用,把 C 語言轉換爲處理器執行的基本指令。彙編代碼很是接近於機器代碼,只不過與二進制機器代碼相比,彙編代碼的可讀性更強,因此理解彙編是理解機器工做的第一步。
一些進程狀態對機器可見,可是 C 語言程序員卻看不到這些,包括
程序計數器(Program counter)
,它存儲下一條指令的地址,在 x86-64 架構中用 %rip
來表示。程序執行時,PC 的初始值爲程序第一條指令的地址,在順序執行程序時, CPU 首先按程序計數器所指出的指令地址從內存中取出一條指令,而後分析和執行該指令,同時將 PC 的值加 1 並指向下一條要執行的指令。
好比下面一個例子。
這是一段數值進行相加的操做,程序啓動,在通過編譯解析後會由操做系統把硬盤中的程序複製到內存中,示例中的程序是將 123 和 456 執行相加操做,並將結果輸出到顯示器上。因爲使用機器語言難以描述,因此這是通過翻譯後的結果,實際上每一個指令和數據均可能分佈在不一樣的地址上,但爲了方便說明,把組成一條指令的內存和數據放在了一個內存地址上。
寄存器文件(register file)
包含 16 個命名的位置,用來存儲 64 位的值。這些寄存器能夠存儲地址和整型數據。有些寄存器用於跟蹤程序狀態,而另外一些寄存器用於保存臨時數據,例如過程的參數和局部變量,以及函數要返回的值。這個 文件
是和磁盤文件無關的,它只是 CPU 內部的一塊高速存儲單元。有專用的寄存器,也有通用的寄存器用來存儲操做數。條件碼寄存器
用來保存有關最近執行的算術或邏輯指令的狀態信息。這些用於實現控件或數據流中的條件更改,例如實現 if 和 while 語句所需的條件更改。咱們都學太高級語言,高級語言中的條件控制流程主要分爲三種:順序執行、條件分支、循環判斷
三種,順序執行是按照地址的內容順序的執行指令。條件分支是根據條件執行任意地址的指令。循環是重複執行同一地址的指令。
下面以條件分支爲例來講明程序的執行過程(循環也很類似)
程序的開始過程和順序流程是同樣的,CPU 從 0100 處開始執行命令,在 0100 和 0101 都是順序執行,PC 的值順序+1,執行到 0102 地址的指令時,判斷 0106 寄存器的數值大於 0,跳轉(jump)到 0104 地址的指令,將數值輸出到顯示器中,而後結束程序,0103 的指令被跳過了,這就和咱們程序中的 if()
判斷是同樣的,在不知足條件的狀況下,指令會直接跳過。因此 PC 的執行過程也就沒有直接+1,而是下一條指令的地址。
向量寄存器
用來存儲一個或者多個整數或者浮點數值,向量寄存器是對一維數據上進行操做。機器指令只會執行很是簡單的操做,例如將存放在寄存器的兩個數進行相加,把數據從內存轉移到寄存器中或者是條件分支轉移到新的指令地址。編譯器必須生成此類指令的序列,以實現程序構造,例如算術表達式求值,循環或過程調用和返回
我相信各位應該都知道彙編語言的出現背景吧,那就是二進制表示數據,太複雜太龐大了,爲了解決這個問題,出現了彙編語言,彙編語言和機器指令的區別就在於表示方法上,彙編使用操做數
來表示,機器指令使用二進制來表示,我以前屢次提到機器碼就是彙編,你也不能說我錯,可是不許確。
可是彙編適合二進制代碼存在轉換關係的。
彙編代碼須要通過 彙編器
編譯後才產生二進制代碼,這個二進制代碼就是目標代碼,而後由連接器將其鏈接起來運行。
彙編語言主要分爲如下三類
助記符
,它有對應的機器碼彙編語言的核心是彙編指令,而咱們對彙編的探討也是基於彙編指令展開的。
CPU 是計算機的大腦,它也是整個計算機的核心,它也是執行彙編語言的硬件,CPU 的內部包含有寄存器,而寄存器是用於存儲指令和數據的,彙編語言的本質也就是 CPU 內部操做數所執行的一系列計算。
沒有內存,計算機就像是一個沒有記憶的人類,只會永無休止的重複性勞動。CPU 所需的指令和數據都由內存來提供,CPU 指令經由內存提供,通過一系列計算後再輸出到內存。
磁盤也是一種存儲設備,它和內存的最大區別在於永久存儲,程序須要在內存裝載後才能運行,而提供給內存的程序都是由磁盤存儲的。
通常來講,內存內部會劃分多個存儲單元,存儲單元用來存儲指令和數據,就像是房子同樣,存儲單元就是房子的門牌號。而 CPU 與內存之間的交互是經過地址總線
來進行的,總線從邏輯上分爲三種
CPU 與存儲器之間的讀寫主要通過如下幾步
下面咱們就來具體瞭解一下這三類總線
經過咱們上面的探討,咱們知道 CPU 經過地址總線
來指定存儲位置的,地址總線上能傳送多少不一樣的信息,CPU 就能夠對多少個存儲單元進行尋址。
上圖中 CPU 和內存中間信息交換經過了 10 條地址總線,每一條線可以傳遞的數據都是 0 或 1 ,因此上圖一次 CPU 和內存傳遞的數據是 2 的十次方。
因此,若是 CPU 有 N 條地址總線,那麼能夠說這個地址總線的寬度是 N 。這樣 CPU 能夠尋找 2 的 N 次方個內存單元。
CPU 與內存或其餘部件之間的數據傳送是由數據總線
來完成的。數據總線的寬度決定了 CPU 和外界的數據傳輸速度。8 根數據總線能夠一次傳送一個 8 位二進制數據(即一個字節)。16 根數據總線一次能夠傳輸兩個字節,32 根數據總線能夠一次傳輸四個字節。。。。。。
CPU 與其餘部件之間的控制是經過 控制總線
來完成的。有多少根控制總線,就意味着 CPU 提供了對外部器件的多少種控制。因此,控制總線的寬度決定了 CPU 對外部部件的控制能力。
內存結構
內存 IC 是一個完整的結構,它內部也有電源、地址信號、數據信號、控制信號和用於尋址的 IC 引腳來進行數據的讀寫。下面是一個虛擬的 IC 引腳示意圖
圖中 VCC 和 GND 表示電源,A0 - A9 是地址信號的引腳,D0 - D7 表示的是控制信號、RD 和 WR 都是好控制信號,我用不一樣的顏色進行了區分,將電源鏈接到 VCC 和 GND 後,就能夠對其餘引腳傳遞 0 和 1 的信號,大多數狀況下,+5V 表示1,0V 表示 0。
咱們都知道內存是用來存儲數據,那麼這個內存 IC 中能存儲多少數據呢?D0 - D7 表示的是數據信號,也就是說,一次能夠輸入輸出 8 bit = 1 byte 的數據。A0 - A9 是地址信號共十個,表示能夠指定 00000 00000 - 11111 11111 共 2 的 10次方 = 1024個地址
。每一個地址都會存放 1 byte 的數據,所以咱們能夠得出內存 IC 的容量就是 1 KB。
若是咱們使用的是 512 MB 的內存,這就至關因而 512000(512 * 1000) 個內存 IC。固然,一臺計算機不太可能有這麼多個內存 IC ,然而,一般狀況下,一個內存 IC 會有更多的引腳,也就能存儲更多數據。
內存讀取過程
下面是一次內存的讀取過程。
來詳細描述一下這個過程,假設咱們要向內存 IC 中寫入 1byte 的數據的話,它的過程是這樣的:
A0 - A9
來指定數據的存儲場所,而後再把數據的值輸入給 D0 - D7
的數據信號,並把 WR(write)
的值置爲 1,執行完這些操做後,便可以向內存 IC 寫入數據此篇文章咱們主要探討了指令集、指令集的分類,與彙編有關的硬件,總線都有哪些,分別的做用都是什麼,而後咱們以一次內存讀取過程來鏈接一下 CPU 和內存的交互過程。
原創不易,若有幫助還請各位讀者四連(點在、在看、分享、留言),感謝各位大佬
關注公衆號 程序員cxuan 回覆 cxuan 領取優質資料。
我本身寫了六本 PDF ,很是硬核,連接以下
我本身寫了六本 PDF ,很是硬核,連接以下
我本身寫了六本 PDF ,很是硬核,連接以下