彙編指令入門級整理 | 原力計劃

作者 | AlbertS

出品 | CSDN 博客

前言

我們大都是被高級語言慣壞了的一代,源源不斷的新特性正在逐步添加到各類高級語言之中,彙編作爲最接近機器指令的低級語言,已經很少被直接拿來寫程序了,不過我還真的遇到了一個,那是之前的一個同事,因爲在寫代碼時遇到了成員函數權限及可見性的問題,導致他無法正確調用想執行的函數,結果他就開始在 C++ 代碼裏嵌入彙編了,繞過了種種限制終於如願以償,但是讀代碼的我們傻眼了…

因爲項目是跨平臺的,代碼推送的 Linux 上編譯的時候他才發現,彙編代碼的語法在 Linux 和 Windows 上居然是不一樣的,結果他又用一個判斷平臺的宏定義“完美”的解決了,最終這些代碼肯定是重寫了啊,因爲可讀性太差了,最近在學習左值、右值、左引用和右引用的時候,總是有人用程序編譯生成的中間彙編代碼來解釋問題,看得我迷迷糊糊,所以決定熟悉一下簡單的彙編指令,邊學習邊記錄,方便今後忘記了可以直接拿來複習。

什麼是彙編語言

彙編語言是最接近機器語言的編程語言,引用百科中的一段話解釋爲:

彙編語言(assembly language)是一種用於電子計算機、微處理器、微控制器或其他可編程器件的低級語言,亦稱爲符號語言。在彙編語言中,用助記符代替機器指令的操作碼,用地址符號或標號代替指令或操作數的地址。彙編語言又被稱爲第二代計算機語言。

彙編語言產生的原因

對於絕大多數人來說,二進制程序是不可讀的,當然有能人可以讀,比如第一代程序員,但這類人快滅絕了,直接看二進制不容易看出來究竟做了什麼事情,比如最簡單的加法指令二進制表示爲 00000011,如果它混在一大串01字符串中就很難把它找出來,所以彙編語言主要就是爲了解決二進制編碼的可讀性問題。

彙編與二進制的關係

換句話來說,彙編語言就是把給機器看的二進制編碼翻譯成人話,彙編指令是機器指令的助記符,與機器指令是一一對應的關係,是一種便於閱讀和記憶的書寫格式。有效地解決了機器指令編寫程序難度大的問題,並且使用編譯器,可以很方便的把彙編程序轉譯成機器指令程序,比如之前提到的 00000011 加法指令,對應的彙編指令是 ADD,在調用匯編器時就會把 ADD 翻譯成 00000011。

寄存器

說到彙編指令不得不提到寄存器,寄存器本身是用來存數據的,因爲 CPU 本身只負責邏輯運算,數據需要單獨儲存在其他的地方,但是對於不熟悉寄存器的人來說會有疑惑,數據不是存在硬盤上嗎?或者說數據不是存在內存中嗎?這些想法都沒錯,那麼寄存器是用來做什麼的呢?

寄存器作用

其實硬盤、內存都是用來存儲數據的,但是 CPU 的運算速度遠高於內存的讀寫速度,更不用說從硬盤上取數據了,所以爲了避免被拖慢速度影響效率,CPU 都自帶一級緩存和二級緩存,一些 CPU 甚至增加了三級緩存,從這些緩存中讀寫數據要比內存快很多,但是還是無法使用飛速運轉的 CPU,所以纔會有寄存器的存在。

寄存器不是後來增加的,在最初的計算中就已經設計出來,相比而言,多級緩存出現的更晚一些,通常那些最頻繁讀寫的數據都會被放在寄存器裏面,CPU 優先讀寫寄存器,再通過寄存器、緩存跟內存來交換數據,達到緩衝的目的,因爲可以通過名稱訪問寄存器,這樣訪問速度是最快的,因此也被稱爲零級緩存。

存取速度比較

通過上面的敘述我們可以知道存取速度從高到低分別是: 寄存器 > 1級緩存 > 2級緩存 > 3級緩存 > 內存 > 硬盤,關於它們的存取速度,舉個例子很容易就能明白了,比如我們做菜(CPU工作)時,取手中(寄存器)正拿着的肉和蔬菜肯定是最快的,如果沒有就需要把案板上(1級緩存)處理好的菜拿過來,如果案板上沒有就在更遠一點的洗菜池(2級緩存)中找一找,還沒找到的話就要到冰箱(3級緩存)中看一看了,這時發現家裏真沒有,那去樓下的菜店(內存)去買點吧,轉了一圈發現沒有想要的,最後還是開車去農貿市場(硬盤)買吧。

通過上面這個例子應該能明白它們的速度關係了,既然緩存這麼快,爲什麼不用緩存代替內存,或者將2、3級緩存都換成1級緩存呢?這裏邊有一個成本問題,速度越快對應着價格越高,如果你買過機械硬盤和固態硬盤應該很容易就理解了。

寄存器分類

常用的 x86 CPU 寄存器有8個:EAX 、EBX、ECX、EDX、EDI、ESI、EBP、ESP,據說現在寄存器總數已經超過100個了,等我找到相關資料再來補充,上面這幾個寄存器是最常用的,這些名字也常常出現在彙編的代碼中。

我們常說的32位、64位 CPU 是指數據總線的寬度或根數,而寄存器是暫存數據和中間結果的單元,因此寄存器的位數也就是處理數據的長度與數據總線的根數是相同的,所以32位 CPU 對應的寄存器也應該是32位的。

常用寄存器用途

上面提到大8個寄存器都有其特定的用途,我們以32位 CPU 爲例簡單說明下這些寄存器的作用,整理如下表:

寄存器EAX、AX、AH、AL的關係

在上面的圖標中每個常用寄存器後面還有其他的名字,它們是同一個寄存器不同用法下的不同名字,比如在32位 CPU 上,EAX是32位的寄存器,而AX是EAX的低16位,AH是AX的高8位,而AL是AX的低8位,它們的對照關係如下:

00000000 00000000 00000000 00000000
|===============EAX===============|---4個字節
                  |======AX=======|---2個字節
                  |==AH===|-----------1個字節
                          |===AL==|---1個字節

彙編語言指令

終於說到彙編常用指令了,因爲 linux 和 windows 下的彙編語法是有些不同的,所以下面我們先通過 windows 下的彙編指令來簡單學習一下,後續再來比較兩者的不同。

數據傳送指令

算術運算指令

邏輯運算指令

循環控制指令

轉移指令

Linux 和 windows 下彙編的區別

前面說到 linux 和 windows 下的彙編語法是不同的,其實兩種語法的不同和系統不同沒有絕對的關係,一般在 linux 上會使用 gcc/g++ 編譯器,而在 windows 上會使用微軟的 cl 也就是 MSBUILD,所以產生不同的代碼是因爲編譯器不同,gcc 下采用的是AT&T的彙編語法格式,MSBUILD 採用的是Intel彙編語法格式。

總結

  • 彙編指令是機器指令的助記符,與機器指令是一一對應的

  • AT&T的彙編語法格式和Intel彙編語法格式的是不同的

  • 常用寄存器:EAX 、EBX、ECX、EDX、EDI、ESI、EBP、ESP

  • 存取速度從高到低分別是: 寄存器 > 1級緩存 > 2級緩存 > 3級緩存 > 內存 > 硬盤

  • 常用的彙編指令:mov、je、jmp、call、add、sub、inc、dec、and、or

版權聲明:本文爲CSDN博主「AlbertS」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。

原文鏈接:https://blog.csdn.net/albertsh/article/details/106041560

【END】

更多精彩推薦
  ☞華爲全球分析師大會:HMS Core全球開發者應用集成的數量加速增長,打造全場景智慧體驗
☞騰訊人均月薪 8 萬,恍恍惚惚,又被平均了?
☞200 萬年薪請不到!清華姚班到底有多牛?| 原力計劃
☞量子計算與AI“雙拳”出擊,他們鎖定38種潛在抗疫藥物
☞我們已經不用AOP做操作日誌了!| 原力計劃
☞國外這三位帥小夥,居然搞了個用比特幣付款、無人機運送的水培沙拉項目?
你點的每個“在看”,我都認真當成了喜歡
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章