指令集是處理器體系架構的重要組成部分。指令集有兩個發展方面,包含以x86為代表的cisc(複雜指令集)和以arm、mips為代表的risc(精簡指令集)。cisc的目標是盡可能將經常使用的功能用最少甚至一條指令來實現,因此該指令相應的執行電路往往是複雜的,其側重的是硬體功能的實現;risc則相反,其是將複雜的執行電路進行分解,即用盡可能簡單的多指令去描寫敘述該功能,以軟體來減少硬體的複雜度,因此risc對編譯器的要求比較高。cisc的指令長度是可變的,執行週期也不固定,而risc則是定長的、往往都是單週期執行。暫存器多也是risc的特點。
本文的重點不在於具體比較risc和cisc,而是介紹cpu指令的編碼和解碼。我們都知道cpu的流水線執行過程有取指、解碼、執行、訪存和回寫(參看博文:cpu指令的流水線執行
),但非常多人對於這些步驟的理解都只在概念層面上的,有必要對其進行具體闡述,理解cpu指令的設計和實現。
我們都知道c語言是對現實問題的解決方法和過程的高度抽象,其語法主要包含數值、邏輯運算和分支控制轉移。數值運算就是加減乘除(比較也是減法),邏輯運算就是與、或、非、異或等,分支控制轉移包含if/else、for、while等語法。組合語言是在機器層面上對c語言的理解和建構,其指令相同也包含數值、邏輯運算、分支控制轉移,可是一行c語言可能須要多條彙編指令才幹實現。同一時候因為指令在記憶體上,而cpu訪問暫存器要比訪問記憶體要快得多,所以cpu的運算一般都在暫存器中進行,因此組合語言一般都須要新增記憶體和暫存器直接的資料載入/儲存指令。cpu僅僅認識二進位制輸入,所以能夠把組合語言當次硬體層面上的偽**,其便於開發者熟記,相同是低階語言。
指令的編碼就是實現組合語言到二進位制機器碼的過程,其是彙編器實現的(編譯器是將c語言轉為組合語言)。 如今如果某種簡單的cpu僅僅支援4種功能:包含
1)加法 add rd,rs,rn , 結果是rd=rs+rn
2)減法 subrd,rs,rn , 結果是rd=rs-rn
3)資料傳送 mov rd,rs,結果是rd=rs
4)資料載入 ldr rd,[rs] ,結構是將記憶體中以rs暫存器的值為位址取值賦給rd
怎樣進行編碼呢?
1)首先將指令分為操作碼+運算元 兩個部分,操作碼即代表指令功能,如add、sub等,其在cpu中就代表某種詳細的電路,如add就代表加法電路,sub代表減法電路;運算元即是代表功能的輸入和輸出,相應電路的輸入和輸出。
2)如今共同擁有4種功能,那至少須要2個位元來進行編碼,如00代表add,01代表sub,10代表mov,11代表ldr;
3)運算元的編碼,如果暫存器共同擁有8個,rd,rs,rn都是當中的乙個,即d,s,n的範圍是0到7,那至少須要3個位元來編碼,如000代表r0,001代表r1,以此類推,111代表r7.
那要實現以上四種功能指令,總共須要2+3+3+3=11個位元進行編碼。如sub r6,r1,r2,即r1減去r2的值賦給r7,那其編碼就是01 110 001 010.
理解完指令的編碼,那指令的解碼應該是比較好理解的。取指就是依據當前程式計數暫存器pc(如果硬體電路規定r7就是暫存器pc)的值從記憶體中取出機器碼指令,該機器碼的值是01 110 001 010。接下來的過程就是解碼,即依據最先的兩個位元01送入解碼器,選擇為減法電路;110即解碼選擇為r6,001解碼選擇r1,010解碼選擇r2. 再接著的就是指令的執行了,執行就是減法單元電路對兩個輸入(r1,r2)進行運算,將結果賦給r6.
取指和解碼都是cpu的控制單元(cu)完畢的,執行是alu(邏輯運算單元)完畢,能夠將alu看出是非常多種電路的集合。cpu指令的設計和指令編碼息息相關。
arm和mips cpu都是32位字長,因此指令編碼是32位元,可以支援和表達很多其它的功能(操作碼)和暫存器(運算元)。如arm體系是r0到r15,因此須要4個位元來表示,當然arm的暫存器還有組的概念,即cpu在不同的工作模式時看到的暫存器可能是不同的,如r13,r14等。這些解碼時不僅須要指令運算元作為輸入,還須要當前狀態暫存器的值作為輸入。
16位指令集是由於什麼產生的呢?是由於相同的一段c語言**,用16位指令進行編碼比32位編碼可以節省30%的**量,**量越少,那占用的記憶體就越少,自然成本越低。在mcu領域,一般都是成本敏感的,所以16為指令在mcu領域有很廣泛的使用。
arm和mips的指令設計是以32位為基礎進行設計,其執行也是32作為輸入的,那怎樣在32位指令集中實現16位呢?我們都知道二八原理,即20%的指令的使用率會達到80%,所以我們對這20%的指令(其是32位指令的乙個子集)進行編碼,自然能夠用較少的位元數來進行編碼,而在16位指令使用時,我們能夠強制要求其僅僅使用一部分暫存器,那自然能夠以更少的位元數來進行暫存器的編碼。能夠將16位指令集看成是32位指令集的乙個子集,cpu在解碼階段先將16為指令轉化為相應的32位指令,再進行解碼、執行。
arm的16位指令集為thumb指令集,mips的16為指令集為mips16指令集。至於32位指令集和16位指令集之間的無縫切換,請參看還有一篇博文:32位和16位指令集模式自己主動切換機制。
編碼,解碼與亂碼的原理與亂碼解決
在做開發中肯定經常遇到亂碼這種事情,對於新手來說比較頭疼,很難解決。但其實只要等你了解的知識夠了之後,你就會發現太簡單了,而且高手是不會碰到亂碼的 首先用圖來表達這個內容,若看的懂圖,後面的長長的字就不用看了。以iso 8859 1與utf 8為例 前言在說編譯碼之前,有必要提一下為什麼要編碼,解碼...
Base64編碼與解碼原理
base64編碼是使用64個可列印ascii字元 a z a z 0 9 將任意位元組序列資料編碼成ascii字串,另有 符號用作字尾用途。base64編碼與解碼的基礎索引表如下 1 base64編碼過程 base64將輸入字串按位元組切分,取得每個位元組對應的二進位制值 若不足8位元則高位補0 然...
is 編碼與解碼
is 和 主要是數字和字串的比較 1 區別 比較的是兩邊的值 is比較的是兩邊值的id id獲取的方法 id 2 小資料池 5 256 3 字串中特殊字元有id不同 4 字串中單個字元 20以內,記憶體位址是一樣的 21以上記憶體位址不一致 編碼與解碼 1 encode a 把明文編譯成a格式 de...