彙編入門第一篇,小白也能看懂

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數組

因此你就能理解緩存

assembly001

這本書是講啥的了。安全

它主要是基於 MIPS 體系結構把馮諾依曼體系的五大組件進行了逐一的硬件實現 + 軟件設計介紹,更爲重要的是引入了諸多並行計算的內容,這是大部分教材中忽略或者內容較少的,會根據這個思路把並行相關的內容,結合 OpenMP, CUDA 和 Hadoop/Spark 總體融入到新書中,畢竟這是將來發展的趨勢markdown

還有這本書網絡

assembly002

這本書又是講啥的。

這本書是講 RISC-V 指令集的,由於指令集的不一樣也區分了三個版本,三個版本???嗯,還有下面這個

assembly003

這本書是講 ARM 指令集的。

因此通常在看 CASPP 的時候併發的看看這本書是很是不錯的選擇。

精簡指令集通常具備以下特徵

  • 統一的指令編碼
  • 通用的寄存器,通常會區分整數和浮點數
  • 簡單的尋址模式,複雜尋址模式被簡單指令序列來取代
  • 支持不多偏門的類型,例如 RISC 支持字節字符串類型。

複雜指令集

複雜指令集的英文是 Complex Instruction Set Computing, CISC,是一種微處理器指令集架構,也被譯爲複雜指令集。

複雜指令集包括 System/360、VAX、x86 等

複雜指令集能夠說是在精簡指令集之上做出的改變。

複雜指令集的特色是指令數目多而複雜,每條指令字長並不相等,計算機必須加以判讀,併爲此付出了性能的代價。

通常來講,提高 CPU 性能的方法有以下這幾種

  • 增長寄存器的大小
  • 增進內部的並行性
  • 增長高速緩存的大小
  • 增長核心時脈的速度
  • 加入其餘功能,例如 IO 和計時器
  • 加入向量處理器
  • 硬件多線程技術

比較抽象,咱們後面會組織成文章具體介紹一下。

C 編譯器會接收其餘操做並把其轉換爲彙編語言輸出,彙編語言是機器級別的代碼表示。咱們以前介紹過,C 語言程序的執行過程分爲下面這幾步

assembly004

下面咱們更多的討論都是基於彙編代碼來討論。

咱們平常所接觸的高級語言,都是通過了層層封裝的結果,因此咱們日常是接觸不到彙編語言的,更不會用匯編語言來進行編程,這就和你不知道操做系統的存在同樣,但其實你每一個操做,甚至你雙擊一個圖標都和操做系統有關係。

高級語言的抽象級別很高,可是通過了層層抽象以後,高級語言的執行效率確定沒有彙編語言高,也沒有彙編語言可靠。

可是高級語言有更大的優勢是其編譯後可以在不一樣的機器上運行,彙編語言針對不一樣的指令集有不一樣的表示。而且高級語言學習來更加通俗易懂,下降計算機門檻,讓內卷更加嚴重(固然這是開個玩笑,冒犯到請別當真)。

話很少說,瞭解底層必須瞭解彙編語言。不然一個 synchronized 底層實現就可以讓你頭疼不已。並且,每天飄着也很差,早晚要落地。

瞭解彙編代碼也有助於咱們優化程序代碼,分析代碼中隱含的低效率,而且這種優化方法一旦優化成功,將是量級的提升,而不是改改 if...else ,使用一個新特性所能比的。

機器級代碼

計算機系統使用了多種不一樣形式的抽象,能夠經過一個簡單的抽象模型來隱藏實現細節。對於機器級別的程序來講,有兩點很是重要。

首先第一點,定義機器級別程序的格式和行爲被稱爲 指令集體系結構或指令集架構(instruction set architecture), ISA。ISA 定義了進程狀態、指令的格式和每個指令對狀態的影響。大部分的指令集架構包括 ISA 用來描述進程的行爲就好像是順序執行的,一條指令執行結束後,另一條指令再開始。處理器硬件的描述要更復雜,它能夠同時並行執行許多指令,可是它採用了安全措施來確保總體行爲與 ISA 規定的順序一致。

第二點,機器級別對內存地址的描述就是 虛擬地址(virtual address),它提供了一個內存模型來表示一個巨大的字節數組。

編譯器在整個編譯的過程當中起到了相當重要的做用,把 C 語言轉換爲處理器執行的基本指令。彙編代碼很是接近於機器代碼,只不過與二進制機器代碼相比,彙編代碼的可讀性更強,因此理解彙編是理解機器工做的第一步。

一些進程狀態對機器可見,可是 C 語言程序員卻看不到這些,包括

  • 程序計數器(Program counter),它存儲下一條指令的地址,在 x86-64 架構中用 %rip 來表示。

程序執行時,PC 的初始值爲程序第一條指令的地址,在順序執行程序時, CPU 首先按程序計數器所指出的指令地址從內存中取出一條指令,而後分析和執行該指令,同時將 PC 的值加 1 並指向下一條要執行的指令。

好比下面一個例子。

assembly005

這是一段數值進行相加的操做,程序啓動,在通過編譯解析後會由操做系統把硬盤中的程序複製到內存中,示例中的程序是將 123 和 456 執行相加操做,並將結果輸出到顯示器上。因爲使用機器語言難以描述,因此這是通過翻譯後的結果,實際上每一個指令和數據均可能分佈在不一樣的地址上,但爲了方便說明,把組成一條指令的內存和數據放在了一個內存地址上。

  • 整數寄存器文件(register file)包含 16 個命名的位置,用來存儲 64 位的值。這些寄存器能夠存儲地址和整型數據。有些寄存器用於跟蹤程序狀態,而另外一些寄存器用於保存臨時數據,例如過程的參數和局部變量,以及函數要返回的值。這個 文件 是和磁盤文件無關的,它只是 CPU 內部的一塊高速存儲單元。有專用的寄存器,也有通用的寄存器用來存儲操做數。
  • 條件碼寄存器 用來保存有關最近執行的算術或邏輯指令的狀態信息。這些用於實現控件或數據流中的條件更改,例如實現 if 和 while 語句所需的條件更改。咱們都學太高級語言,高級語言中的條件控制流程主要分爲三種:順序執行、條件分支、循環判斷三種,順序執行是按照地址的內容順序的執行指令。條件分支是根據條件執行任意地址的指令。循環是重複執行同一地址的指令。
    • 順序執行的狀況比較簡單,每執行一條指令程序計數器的值就是 + 1。
    • 條件和循環分支會使程序計數器的值指向任意的地址,這樣一來,程序即可以返回到上一個地址來重複執行同一個指令,或者跳轉到任意指令。

下面以條件分支爲例來講明程序的執行過程(循環也很類似)

assembly006

程序的開始過程和順序流程是同樣的,CPU 從 0100 處開始執行命令,在 0100 和 0101 都是順序執行,PC 的值順序+1,執行到 0102 地址的指令時,判斷 0106 寄存器的數值大於 0,跳轉(jump)到 0104 地址的指令,將數值輸出到顯示器中,而後結束程序,0103 的指令被跳過了,這就和咱們程序中的 if() 判斷是同樣的,在不知足條件的狀況下,指令會直接跳過。因此 PC 的執行過程也就沒有直接+1,而是下一條指令的地址。

  • 一組 向量寄存器用來存儲一個或者多個整數或者浮點數值,向量寄存器是對一維數據上進行操做。

機器指令只會執行很是簡單的操做,例如將存放在寄存器的兩個數進行相加,把數據從內存轉移到寄存器中或者是條件分支轉移到新的指令地址。編譯器必須生成此類指令的序列,以實現程序構造,例如算術表達式求值,循環或過程調用和返回

認識彙編

我相信各位應該都知道彙編語言的出現背景吧,那就是二進制表示數據,太複雜太龐大了,爲了解決這個問題,出現了彙編語言,彙編語言和機器指令的區別就在於表示方法上,彙編使用操做數來表示,機器指令使用二進制來表示,我以前屢次提到機器碼就是彙編,你也不能說我錯,可是不許確。

可是彙編適合二進制代碼存在轉換關係的。

彙編代碼須要通過 彙編器 編譯後才產生二進制代碼,這個二進制代碼就是目標代碼,而後由連接器將其鏈接起來運行。

assembly007

彙編語言主要分爲如下三類

  • 彙編指令:它是一種機器碼的助記符,它有對應的機器碼
  • 僞指令:沒有對應的機器碼,由編譯器執行,計算機並不執行
  • 其餘符號,好比 +、-、*、/ 等,由編譯器識別,沒有對應的機器碼

彙編語言的核心是彙編指令,而咱們對彙編的探討也是基於彙編指令展開的。

與彙編有關的硬件和概念

CPU

CPU 是計算機的大腦,它也是整個計算機的核心,它也是執行彙編語言的硬件,CPU 的內部包含有寄存器,而寄存器是用於存儲指令和數據的,彙編語言的本質也就是 CPU 內部操做數所執行的一系列計算。

內存

沒有內存,計算機就像是一個沒有記憶的人類,只會永無休止的重複性勞動。CPU 所需的指令和數據都由內存來提供,CPU 指令經由內存提供,通過一系列計算後再輸出到內存。

磁盤

磁盤也是一種存儲設備,它和內存的最大區別在於永久存儲,程序須要在內存裝載後才能運行,而提供給內存的程序都是由磁盤存儲的。

總線

通常來講,內存內部會劃分多個存儲單元,存儲單元用來存儲指令和數據,就像是房子同樣,存儲單元就是房子的門牌號。而 CPU 與內存之間的交互是經過地址總線來進行的,總線從邏輯上分爲三種

  • 地址線
  • 數據線
  • 控制線
assembly008

CPU 與存儲器之間的讀寫主要通過如下幾步

讀操做步驟

  • CPU 經過地址線發出須要讀取指令的位置
  • CPU 經過控制線發出讀指令
  • 內存把數據放在數據線上返回給 CPU

寫操做步驟

  • CPU 經過地址線發出須要寫出指令的位置
  • CPU 經過控制線發出寫指令
  • CPU 把數據經過數據線寫入內存

下面咱們就來具體瞭解一下這三類總線

地址總線

經過咱們上面的探討,咱們知道 CPU 經過地址總線來指定存儲位置的,地址總線上能傳送多少不一樣的信息,CPU 就能夠對多少個存儲單元進行尋址。

assembly009

上圖中 CPU 和內存中間信息交換經過了 10 條地址總線,每一條線可以傳遞的數據都是 0 或 1 ,因此上圖一次 CPU 和內存傳遞的數據是 2 的十次方。

因此,若是 CPU 有 N 條地址總線,那麼能夠說這個地址總線的寬度是 N 。這樣 CPU 能夠尋找 2 的 N 次方個內存單元。

數據總線

CPU 與內存或其餘部件之間的數據傳送是由數據總線來完成的。數據總線的寬度決定了 CPU 和外界的數據傳輸速度。8 根數據總線能夠一次傳送一個 8 位二進制數據(即一個字節)。16 根數據總線一次能夠傳輸兩個字節,32 根數據總線能夠一次傳輸四個字節。。。。。。

控制總線

CPU 與其餘部件之間的控制是經過 控制總線 來完成的。有多少根控制總線,就意味着 CPU 提供了對外部器件的多少種控制。因此,控制總線的寬度決定了 CPU 對外部部件的控制能力。

一次內存的讀取過程

內存結構

內存 IC 是一個完整的結構,它內部也有電源、地址信號、數據信號、控制信號和用於尋址的 IC 引腳來進行數據的讀寫。下面是一個虛擬的 IC 引腳示意圖

assembly010

圖中 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 會有更多的引腳,也就能存儲更多數據。

內存讀取過程

下面是一次內存的讀取過程。

assembly011

來詳細描述一下這個過程,假設咱們要向內存 IC 中寫入 1byte 的數據的話,它的過程是這樣的:

  • 首先給 VCC 接通 +5V 的電源,給 GND 接通 0V 的電源,使用 A0 - A9 來指定數據的存儲場所,而後再把數據的值輸入給 D0 - D7 的數據信號,並把 WR(write)的值置爲 1,執行完這些操做後,便可以向內存 IC 寫入數據
  • 讀出數據時,只須要經過 A0 - A9 的地址信號指定數據的存儲場所,而後再將 RD 的值置爲 1 便可。
  • 圖中的 RD 和 WR 又被稱爲控制信號。其中當WR 和 RD 都爲 0 時,沒法進行寫入和讀取操做。

總結

此篇文章咱們主要探討了指令集、指令集的分類,與彙編有關的硬件,總線都有哪些,分別的做用都是什麼,而後咱們以一次內存讀取過程來鏈接一下 CPU 和內存的交互過程。

原創不易,若有幫助還請各位讀者四連(點在、在看、分享、留言),感謝各位大佬

關注公衆號 程序員cxuan 回覆 cxuan 領取優質資料。

我本身寫了六本 PDF ,很是硬核,連接以下

我本身寫了六本 PDF ,很是硬核,連接以下

我本身寫了六本 PDF ,很是硬核,連接以下

cxuan 嘔心瀝血肝了四本 PDF。

cxuan 又肝了兩本 PDF。

相關文章
相關標籤/搜索