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