- 匯編語言編程基礎:基于LoongArch
- 孫國云 敖琪 王銳
- 3377字
- 2023-03-10 16:38:16
1.1 計算機語言
前文所羅列的語言統稱為計算機語言。計算機語言就是用于人和計算機之間交流的語言。計算機是一組電子器件,要讓它完成特定的工作,就需要向它輸入一組它能識別和執行的語言(或者叫指令)。和人類語言一樣,計算機語言也有一套標準的語法規范,有了規范才得以讓計算機理解我們的意圖并遵照執行。
計算機語言的種類很多,從使用層次的角度常被分成機器語言、匯編語言和高級語言三大類。簡單來說,離計算機處理器最遠(需要更多的編譯流程后才能被計算機識別和執行)、層次最高(更接近自然語言和數學公式)的是高級語言,例如C、C++、Java等都屬于高級語言;中間層次的是匯編語言;離計算機最近、處于最低層次的是機器語言,機器語言是唯一可以被計算機直接識別和執行的語言。絕大多數的計算機軟件開發人員(或稱程序員)通常使用更接近人類語言語法規則、更易于編寫的高級語言來編寫程序,然后利用編譯器、匯編器把高級語言一步步轉換成計算機可以識別的機器語言,最終交由計算機處理器執行并得出結果。這個流程如圖1-1所示。

圖1-1 計算機語言轉換過程
圖1-1簡單描繪了高級語言到機器語言的轉換過程,涉及的工具是編譯器和匯編器。其中編譯器負責把高級語言(比如C++語言)翻譯成匯編語言,匯編器又把匯編語言翻譯成機器語言。而機器語言就是最終可以被計算機識別和執行的語言。
下面按照與計算機處理器的距離,以由近及遠的順序分別介紹機器語言、匯編語言和高級語言。
1.1.1 機器語言
機器語言是計算機能直接識別和執行的程序語言,它的表示形式是二進制。進制就是記數的一種方法,我們最為熟悉的十進制,就是用0~9共10個數來表示的,遵循“逢十進一”的進制規則。而二進制只有“0”和“1”兩個數,遵循“逢二進一”的規則。計算機的硬件作為一種電路元件,最容易用有電和沒電狀態來與外界進行交互,這兩種狀態,也稱高電平和低電平,分別對應到二進制數的“1”和“0”,每個數字被稱為一位(bit)。
機器語言由多條機器指令(簡稱指令)組成。一條指令由固定長度的二進制數組成,用于指導計算機執行一個動作,例如加法運算、減法運算、與運算、從內存讀取數據等。因此,指令是計算機執行的基本單位。計算機呈現給程序員的全部指令的集合就稱為指令集或指令系統。可以說指令系統是軟件和硬件的接口層,我們就是通過這個接口層指導計算機處理器為我們工作。指令系統有很多,常見的有x86、ARM等。中央處理器(Central Processing Unit,CPU)是計算機中的核心部件,其功能主要是解釋指令以及處理計算機軟件中的數據。特定的CPU只能識別特定指令,比如x86指令只能被采用x86指令集的處理器識別,而不能被采用ARM或MIPS指令集的處理器識別。一般而言指令集和體系架構是兩個同義詞,都包含一組指令集和一些寄存器。
龍芯指令系統中一條指令占用32位。比如我們要讓龍芯處理器完成一個加法操作,它的機器指令可能如下:
0000 0010 1100 0001 0000 0000 0110 0011
這是讓人很頭疼的一串數字,因為我們很難直觀讀出這32個0和1的組合的語義。但又不是沒有規律可循,因為機器指令同自然語言和高級計算機語言一樣,是有語法規范的。一條機器指令長度固定(例如龍芯指令長度為32位),由操作碼和操作數兩部分組成,操作數又分為源操作數和目的操作數。這里拿C語言做個簡單的比喻。
long c = a + 2;
這里可以認為符號“+”是操作碼,表示這是個加法操作。變量a和常數2為源操作數,變量c即目的操作數,用于存放加法運算的結果。機器指令的語法規范語義也很類似,不過機器指令中的操作碼不僅要表示運算類別(比如加法、減法、乘法等),還要表示是哪種數據類型(比如int、double、long等)的運算。同時機器指令中的操作數為寄存器(寄存器是計算機中臨時存儲數據的器件)或者常數。例如龍芯指令集中加法運算指令的語法規范如圖1-2所示。

圖1-2 龍芯指令集中加法運算指令的語法規范
從圖1-2可以看出,在龍芯指令集中,一條指令的長度為32位。對于加法指令,32位中的高10位代表操作碼。0b0000001010代表32位的加法指令(ADDI.W),0b0000001011代表64位數的加法指令(ADDI.D)。接下來的12位表示一個常數;再分別用兩個5位表示源寄存器操作數ri和目的寄存器操作數rd,ri和rd可以是龍芯指令集提供的32個通用寄存器中的任意一個。
對照圖1-2,我們可以解讀出這條機器指令的語義。其中高10位(0000 0010 11)為操作碼,語義為帶立即數的64位數(對應C語言的long類型)加法運算;接下來的12位(00 0001 0000 00)為第一個源操作數,且該源操作數是常數,換算成十進制數值為64;再接下來的5位(00 011)為第二個源操作數,且該源操作數是寄存器,換算成十進制數值為3,即代表第3個寄存器;最后的5位(0 0011)為目的操作數,看來也是第3個寄存器。故這條機器指令功能是實現第3個寄存器值和常數64的加法運算,將結果存入第3個寄存器。龍芯匯編指令的寫法就是addi.d r3, r3, 64。此條機器指令按語法規范表示為
0000 0010 11 | 00 0001 0000 00 | 00 011 | 0 0011
操作碼 第一個源操作數 第二個源操作數 目的操作數
要解讀程序中每一條機器指令所代表的意思,要不斷地對照指令手冊來翻譯。推想開來,我們要讓計算機完成一個功能可能需要成千上萬個這樣的指令,如果使用機器指令編寫,難度可想而知。故有了后來更易讀、易編寫的匯編語言和高級語言。
1.1.2 匯編語言
匯編語言可以看作機器語言的升級版,用一些容易理解和記憶的字母、單詞來代替特定的機器指令。通過這種方法讓我們更容易閱讀和理解程序正在執行的功能。比如1.1.1小節中龍芯指令架構下實現兩個數的加法操作,其對應的機器指令和匯編指令分別如下:
機器指令: 0000 0010 1100 0001 0000 0000 0110 0011
匯編指令: addi.d r3, r3, 64
從對應的匯編指令的書寫上更容易解讀出這條指令的語義:實現寄存器r3和常數64的加法操作,并將結果寫回寄存器r3。這樣我們就省去了對照指令手冊逐個翻譯操作碼和操作數來解讀指令語義的過程。一條匯編指令通常由助記符和操作數兩部分組成。助記符對應機器指令中的操作碼,例如這里的addi.d就是助記符,代表這是一個64位加法操作;操作數代表指令的計算對象,例如這里的兩個r3寄存器和常數64。
通過這個例子可以看到,使用匯編語言,程序員不用關心這條指令對應的二進制數是多少,匯編器會幫助我們把它翻譯成二進制的機器語言,編程效率得到很大提高。
匯編語言和機器語言一樣都是和計算機體系架構強綁定的低級語言。也就是說,用龍芯匯編指令集編寫的程序在不加以轉換的情況下,不可能運行在基于x86指令集或ARM指令集的處理器上,反之亦然。
1.1.3 高級語言
高級語言是一個相對概念,通常可解讀為越是易于程序員高效編寫的語言越高級。例如剛開始出現C語言時,人們認為C語言比匯編語言高級,故稱C語言為高級語言,而匯編語言為低級語言,當Java、Python語言出現后,人們又認為C語言不夠高級。本書提到的高級語言是相對于匯編語言而言的,即不再強依賴計算機處理器的硬件體系架構、表達方式更接近自然語言和數學公式的程序設計語言,比如C、C++、Java、Go等。這些語言本身都是獨立于處理器架構的,都有自己的語法規則且不能直接被計算機識別和執行,需要編譯器和匯編器的翻譯過程,相關程序被轉變為機器指令后才被處理器識別和執行。例如要實現一個數的累加運算,使用C語言的編寫如下:
++a;
一條語句就完成了變量a的累加功能,如果a初始值為1,那么++a執行后,a的值為2。這條語句對應的匯編語言指令至少需要3條,即首先從內存地址加載a的初始值到一個寄存器,然后進行這個寄存器和常數1的加法操作,最后把結果寫回內存地址。這個過程可用如下龍芯匯編指令表示:
load r3, [addr] //從內存地址addr加載值到寄存器r3
add r4, r3, 1 //加法計算r3+1,將結果寫到寄存器r4
store r4, [addr] //把寄存器r4的值寫回內存地址addr
對比后不難發現,C語言比匯編語言更直觀,更方便程序員編程。而且同樣功能的高級語言程序只需要編寫一次,對應不同體系架構平臺的機器語言可由對應的編譯器生成。
高級語言設計思想發展的主旨是更便于程序員快速編程。編程思想經歷了面向過程(將一個功能塊定義為一個函數/方法,以C語言為代表)、面向對象(把相關的數據、函數/方法組織為一個整體來管理,以Java語言為代表)、面向函數(即高階函數的出現,很多語言都在“擁抱”高階函數,如Java、Groovy、Scala、JavaScript等)等。未來還可能有面向應用的設計思想轉變,也就是說:只需要告訴程序你要干什么,程序就能自動生成算法,自動進行處理。高級語言設計思想的不斷進化,讓計算機語言越來越接近人類語言,也更智能,編程效率也越來越高,使得程序員可把更多時間花費在解決復雜業務場景上。
- 多媒體CAI課件設計與制作導論(第二版)
- OpenDaylight Cookbook
- Mastering Objectoriented Python
- Mastering phpMyAdmin 3.4 for Effective MySQL Management
- 深入實踐Spring Boot
- OpenCV for Secret Agents
- 基于免疫進化的算法及應用研究
- 名師講壇:Spring實戰開發(Redis+SpringDataJPA+SpringMVC+SpringSecurity)
- C語言程序設計實驗指導 (第2版)
- Android Wear Projects
- 編程可以很簡單
- Java Hibernate Cookbook
- VC++ 2008專題應用程序開發實例精講
- Spring Microservices
- Visual Basic程序設計