? ? ? ??感謝原著作者對人類文化的傳播做出的努力!以下內容直譯為主,意譯為輔,同時筆者可能會加入個人觀點以方便理解。如有翻譯不當的地方希望各位同仁積極指出,如有必要的話請做出引證,以助于筆者翻譯水平的提高,同時也有利于其它讀者的學習,進步。天朗氣清,惠風和暢,祝各位生活愉快!
? ? ??
問題:我剛開始學習ARM匯編語言,不太清楚如何利用MOV指令將立即數傳入到寄存器。在ARM參考手冊及我的課本中,都說MOV指令后跟的立即數變化范圍是0~255。但是當我在ADS1.2集成開發(fā)環(huán)境中進行測試時,下述指令語句卻正常運行。
MOV???R2,?#0xFFFFFFFF
根據上述說法數字0xFFFFFFFF不是超出了范圍嗎?為什么會出現這種情況呢?
回答:ARM可以對立即數進行一些特定的操作,因為ARM核內集成了桶形移位器,ARM操作碼可以借此完成一些特定操作。下文介紹ARM匯編器使用了哪些技巧,從而使一個大的立即數達到ARM指令可處理的小空間的。
—————————————————————————————————————————————————
不是任意一個32位數都可以表示成32位指令字。ARM數據處理指令在指令字中有12位空間用于存數值。如下圖所示它是由4位循環(huán)移位值和8位立即數組成:
4位循環(huán)移位值保存在11-8位上,它乘以2從而得到循環(huán)移位范圍0-30。
根據這種設計原則,我們可以表示的立即數如下:
0x000000FF 0x00000FF0 0xFF000000 0xF000000F
而像下面這樣的立即數
0x000001FE 0xF000F000 0x55550000
是不符合ARM指令處理規(guī)范的,所以無法直接處理。
匯編器會把大的數轉化成循環(huán)移位形式,即由8位二進制數循環(huán)右移偶數次得到,循環(huán)移位范圍是0-30。不合法的立即數會產生錯誤。
有些匯編器會使用一些其它技巧,如使用MVN代替MOV得到一些數的按位取反數。例如指令MOV ?r0, #0xFFFFFFFF可以被匯編為MVN? r0, #0。
以上這種問題導致有些常數是ARM友好的(ARM friendly),有些則不是。所以仔細研究一下你正在使用的數,也許還有再進一步優(yōu)化的余地。
你可以使用指令序列創(chuàng)建一些單條指令無法操作的常數,如:
MOV???r2,#0x55??????????????;?R2?=?0x00000055 ORR???r2,?r2,?r2,?LSL?#8????;?R2=?0x00005555 ORR???r2,?r2,?r2,?LSL?#16???;?R2?=0x55555555
或者從存儲器中裝載數值:
LDR??r2,?=0x55555555
如果可能的話,偽指令LDR ?Rx,=const會嘗試用一條指令創(chuàng)建常數,否則會生成一個LDR。
—————————————————————————————————————————————————
你所提到的例子可能使用了上文討論的這些技巧,如生成了MVN操作碼來裝載立即數的按位取反值。這些操作并不適用于所有立即數,但是ARM匯編器很機智地知道該如何處理(C編譯器當然也是)。如果有些數無法用移位/取反方法表示,這些數通常會從PC相關的位置裝載或者用幾條指令來創(chuàng)建。