在arm彙編的資料處理指令中經常會使用到常數,而arm彙編中規定使用的常數必 須是立即數。arm立即數的是由乙個8位的常數迴圈右移偶數字得到的,其中迴圈右移 的位數由乙個4位2進製的兩倍表示,公式如下:
immediate=immed_8&<(2*rotate_imm4) 「<<」表示迴圈右移 簡單的說乙個常數如果可以由乙個8位的常數迴圈移位偶數字得到,那麼就是立即數。
為什麼會有立即數這樣的規定呢,這是由於所有的arm指令是精簡指令集,指令長度固定都是32位,對於arm資料處理指令自然也是一樣。資料處理指令大致可包含3類,資料傳送指令、資料算術邏輯運算指令和資料比較指令。在一條arm資料處理指令中,除了要包含處理的資料值外,還要標識arm命令名稱,控制位,暫存器等其他資訊。這樣在一條arm資料處理指令中,能用於表示要處理的資料值的位數只能小於32位。
arm在指令格式中設定,只能用指令機器碼32位中的低12位來表示要操作的常數。arm處理器是按32位來處理資料的,arm處理器處理的資料是32位,如果簡單的用這12位來表示,顯然範圍太小了,為了擴充套件到32位,因此使用了構造的方法,在12位中用8位表示基本資料值,用4位表示位移值,通過用8位基本資料值往右迴圈移動4位位移值*2次,來表示要操作的常數。這裡要強調終的迴圈次數是4位位移值乘以2得到的,所以得到的終迴圈次數肯定是乙個偶數,為什麼要乘以2呢,實質還是因為範圍不夠,4位表示位移次數,大才15次,加上8位資料還是不夠32位,這樣只能通過alu的內部結構設計將4位位移次數乘以2,這樣就能用12位表示32位常數了。
通過迴圈偶數字得的到運算元,擴大了運算元的範圍,但也帶來了問題,並不是每個資料都能通過8位基本資料迴圈移動偶數為得到,如果你在arm資料處理指令中使用的運算元,不是立即數,比如mov r1,#0x12345678,編譯器就會報錯,所以我們在使用前必須進行判斷,這也是很多arm相關求職筆試中常考的一道題目。
那怎樣怎麼快速判斷乙個數是否是立即數,對於簡單的數字我們可以直接判斷,比如小於255的數字肯定是立即數。對相對複雜的數字進行判斷就需要先把它轉換為2進製形式,然後根據定義進行判斷了。我這裡總結了個比較快速的方法:
1、把資料轉換成二進位制形式,從低位到高位寫成4位1組的形式,高位一組不夠四位的,在高位前面補0。
2、數1的個數,如果大於8個肯定不是立即數,如果小於等於8進行下面步驟。
3、如果資料中間有連續的大於等於24個0,迴圈左移4的倍數,使高位全為0。
4、找到高位的1,去掉前面大偶數個0。
5、找到低位的1,去掉後面大偶數個0。
6、數剩下的位數,如果小於等於8位,那麼這個數就是立即數,反之就不是立即數。
針對可能現的情況,我舉5個典型例子:
(1)0x4ff (2)0x122 (3)0x234 (4)0xf000000f (5)0x8000007f
例1: 0x4ff
第一步:0100 1111 1111
第二步:其中1的個數是9個,大於8個,判定不是立即數
例2: 0x122
第一步: 0001 0010 0010
第二步: 其中1的個數4個,小於8,繼續
第三步: 其中沒有連續大於等於24個0,繼續
第四部: xx01 0010 0010 (高位前面有3個0,大偶數2,去掉2個0)
第五步: xx10 0011 0010 (低位後面只有1個0,大偶數0)
第六部: 剩下10 0011 0010 共10位,大於8,判定0x122不是立即數
例3: 0x234
第一步: 0010 0011 0100
第二步: 其中1的個數4個,小於8,繼續
第三步: 其中沒有連續大於等於24個0,繼續
第四部: xx10 0011 0100
第五步: xx10 0011 01xx
第六部: 剩下10 0011 01 共8位,等於8,判定0x234是立即數
例4: 0xf000000f
第一步: 1111 0000 0000 0000 0000 0000 0000 1111
第二步: 其中1的個數8個,沒有大於8,繼續
第三步: 其中有連續24個0,迴圈左移4位,使高位全為0
0000 0000 0000 0000 0000 0000 0000 1111 1111
第四部: ***x ***x ***x ***x ***x ***x ***x 1111 1111
第五步: ***x ***x ***x ***x ***x ***x ***x 1111 1111
第六部: 剩下1111 1111共8位,等於8,判定0xf000000f是立即數
例5: 0x8000007f
第一步: 1000 0000 0000 0000 0000 0000 0111 1111
第二步: 其中1的個數8個,沒有大於8,繼續
第三步: 其中有連續24個0,迴圈左移4位,使高位全為0
0000 0000 0000 0000 0000 0000 0111 1111 1000
第四部: ***x ***x ***x ***x ***x ***x 0111 1111 10xx
第五步: ***x ***x ***x ***x ***x ***x 0111 1111 10xx
第六部: 剩下0111 1111 10共10位,等於8,判定0x7000008f是立即數
問題還沒有結束,我們在arm彙編中如何規避立即數這個問題呢,其實可以使用arm彙編ldr偽指令,例如直接把mov指令變為, ldr r1,=0x12345678這樣編譯器就不會報錯了。但這種方法也有弊端會增加開銷和影響執行效率。同時arm彙編中還有有效數的概念,比如 mov r1,#0xffffffff 指令中 0xffffffff 不是立即數,但是是有效數,編譯器自動把原指令變換為 mvn r1,#0,也不會報錯。有效數判定:原數是立即數或者原數反碼是立即數。
ARM指令中如何判斷乙個立即數是有效立即數
在arm處理器的組合語言中,對指令語法格式中的的常數表示式有這樣的規定 該常數必須對應8位位圖,即常數是由乙個8位的常數迴圈移位偶數字得到的。首先從arm指令系統的語法格式說起。一條arm指令語法格式分為如下幾個部分 其中,內的項是必須的,內的項是可選的,如是指令助記符,是必須的,而 為指令執行條件...
ARM指令中如何判斷乙個立即數是有效立即數
在arm處理器的組合語言中,對指令語法格式中的的常數表示式有這樣的規定 該常數必須對應8位位圖,即常數是由乙個8位的常數迴圈移位偶數字得到的。首先從arm指令系統的語法格式說起。一條arm指令語法格式分為如下幾個部分 其中,內的項是必須的,內的項是可選的,如是指令助記符,是必須的,而 為指令執行條件...
ARM中判斷立即數是否有效
在arm立即數定址中,指令中的立即數是有乙個8位的常熟和移動的4 位偶數字得到的,所以每一條指令都包含乙個常數x和移位值y,得到的立即數 x迴圈右移 2 y 給定乙個立即數,判斷其是否合法可以分三步 首先將給定的立即數寫成32位二進位制的形式 然後看能不能用乙個8位的二進位制數包括所有含1的部分,如...