立即數的判斷方法一
時(shi)間(jian):2016-12-14作者:華清遠見
在(zai)ARM匯編(bian)的(de)數據處(chu)理指(zhi)令(ling)中經常(chang)會(hui)使用到常(chang)數,而ARM匯編(bian)中規(gui)定使用的(de)常(chang)數必 須是(shi)立即數。ARM立即數的(de)是(shi)由一個8位的(de)常(chang)數循環(huan)(huan)右(you)(you)移偶數位得到的(de),其中循環(huan)(huan)右(you)(you)移 的(de)位數由一個4位2進制的(de)兩倍表示,公式(shi)如下: immediate=immed_8&<(2*rotate_imm4) “<<”表示(shi)循(xun)環右移 簡單的說一個(ge)常(chang)數(shu)(shu)如(ru)果可以由一個(ge)8位(wei)的常(chang)數(shu)(shu)循(xun)環移位(wei)偶數(shu)(shu)位(wei)得到,那(nei)么就是(shi)立即(ji)數(shu)(shu)。 為什么(me)會有立即數(shu)這(zhe)樣的規(gui)定呢(ni),這(zhe)是由于所有的ARM指(zhi)(zhi)令是精簡(jian)指(zhi)(zhi)令集(ji),指(zhi)(zhi)令長(chang)度固定都是32位(wei),對于ARM數(shu)據(ju)(ju)處(chu)理(li)指(zhi)(zhi)令自然也是一樣。數(shu)據(ju)(ju)處(chu)理(li)指(zhi)(zhi)令大致可包含(han)3類,數(shu)據(ju)(ju)傳(chuan)送指(zhi)(zhi)令、數(shu)據(ju)(ju)算術(shu)邏輯運算指(zhi)(zhi)令和數(shu)據(ju)(ju)比較指(zhi)(zhi)令。在(zai)一條ARM數(shu)據(ju)(ju)處(chu)理(li)指(zhi)(zhi)令中,除了要包含(han)處(chu)理(li)的數(shu)據(ju)(ju)值(zhi)外(wai),還要標識ARM命令名稱,控制(zhi)位(wei),寄(ji)存器等(deng)其他信息。這(zhe)樣在(zai)一條ARM數(shu)據(ju)(ju)處(chu)理(li)指(zhi)(zhi)令中,能用于表示要處(chu)理(li)的數(shu)據(ju)(ju)值(zhi)的位(wei)數(shu)只能小于32位(wei)。 ARM在(zai)指(zhi)令(ling)(ling)格式(shi)中設(she)定,只能用(yong)指(zhi)令(ling)(ling)機器(qi)碼32位(wei)(wei)中的(de)(de)(de)低(di)12位(wei)(wei)來表(biao)示(shi)要(yao)(yao)操作(zuo)的(de)(de)(de)常(chang)數(shu)(shu)(shu)(shu)(shu)(shu)。ARM處(chu)理器(qi)是按32位(wei)(wei)來處(chu)理數(shu)(shu)(shu)(shu)(shu)(shu)據的(de)(de)(de),ARM處(chu)理器(qi)處(chu)理的(de)(de)(de)數(shu)(shu)(shu)(shu)(shu)(shu)據是32位(wei)(wei),如果簡單的(de)(de)(de)用(yong)這12位(wei)(wei)來表(biao)示(shi),顯(xian)然范圍太小(xiao)了(le)(le)(le),為(wei)了(le)(le)(le)擴展到32位(wei)(wei),因(yin)此(ci)使用(yong)了(le)(le)(le)構(gou)造的(de)(de)(de)方法,在(zai)12位(wei)(wei)中用(yong)8位(wei)(wei)表(biao)示(shi)基本數(shu)(shu)(shu)(shu)(shu)(shu)據值,用(yong)4位(wei)(wei)表(biao)示(shi)位(wei)(wei)移(yi)值,通過用(yong)8位(wei)(wei)基本數(shu)(shu)(shu)(shu)(shu)(shu)據值往右循(xun)環(huan)(huan)移(yi)動4位(wei)(wei)位(wei)(wei)移(yi)值*2次(ci)(ci),來表(biao)示(shi)要(yao)(yao)操作(zuo)的(de)(de)(de)常(chang)數(shu)(shu)(shu)(shu)(shu)(shu)。這里要(yao)(yao)強調終的(de)(de)(de)循(xun)環(huan)(huan)次(ci)(ci)數(shu)(shu)(shu)(shu)(shu)(shu)是4位(wei)(wei)位(wei)(wei)移(yi)值乘以(yi)(yi)2得到的(de)(de)(de),所(suo)以(yi)(yi)得到的(de)(de)(de)終循(xun)環(huan)(huan)次(ci)(ci)數(shu)(shu)(shu)(shu)(shu)(shu)肯(ken)定是一個偶(ou)數(shu)(shu)(shu)(shu)(shu)(shu),為(wei)什么要(yao)(yao)乘以(yi)(yi)2呢,實質還是因(yin)為(wei)范圍不夠(gou),4位(wei)(wei)表(biao)示(shi)位(wei)(wei)移(yi)次(ci)(ci)數(shu)(shu)(shu)(shu)(shu)(shu),大才15次(ci)(ci),加上(shang)8位(wei)(wei)數(shu)(shu)(shu)(shu)(shu)(shu)據還是不夠(gou)32位(wei)(wei),這樣只能通過ALU的(de)(de)(de)內(nei)部(bu)結構(gou)設(she)計將4位(wei)(wei)位(wei)(wei)移(yi)次(ci)(ci)數(shu)(shu)(shu)(shu)(shu)(shu)乘以(yi)(yi)2,這樣就(jiu)能用(yong)12位(wei)(wei)表(biao)示(shi)32位(wei)(wei)常(chang)數(shu)(shu)(shu)(shu)(shu)(shu)了(le)(le)(le)。 通過循環偶數(shu)(shu)(shu)位得的到操(cao)作(zuo)數(shu)(shu)(shu),擴大了(le)操(cao)作(zuo)數(shu)(shu)(shu)的范圍(wei),但也帶來了(le)問題,并不(bu)是(shi)每個數(shu)(shu)(shu)據都能通過8位基本數(shu)(shu)(shu)據循環移(yi)動偶數(shu)(shu)(shu)為得到,如(ru)果(guo)你在ARM數(shu)(shu)(shu)據處理指令中使(shi)用(yong)(yong)的操(cao)作(zuo)數(shu)(shu)(shu),不(bu)是(shi)立即(ji)數(shu)(shu)(shu),比(bi)如(ru)MOV R1,#0x12345678,編譯器就會(hui)報錯(cuo),所以我們(men)在使(shi)用(yong)(yong)前必須進(jin)行判斷,這也是(shi)很多(duo)ARM相關(guan)求職筆試(shi)中常考的一(yi)道題目。 那怎(zen)樣怎(zen)么快速(su)判(pan)斷(duan)一個數是否是立(li)即數,對于簡單的數字(zi)我們可以(yi)直接(jie)判(pan)斷(duan),比(bi)如(ru)小于255的數字(zi)肯定是立(li)即數。對相對復雜的數字(zi)進行(xing)判(pan)斷(duan)就需要先把它轉換為2進制形(xing)式,然后根(gen)據定義進行(xing)判(pan)斷(duan)了(le)。我這里(li)總結了(le)個比(bi)較快速(su)的方法: 1、把(ba)數據轉換(huan)成二進制形(xing)(xing)式,從低(di)位(wei)到(dao)高(gao)位(wei)寫(xie)成4位(wei)1組(zu)的形(xing)(xing)式,高(gao)位(wei)一組(zu)不夠四位(wei)的,在高(gao)位(wei)前面(mian)補(bu)0。 2、數1的個數,如(ru)果(guo)大于8個肯定不是(shi)立(li)即數,如(ru)果(guo)小于等于8進(jin)行下面步(bu)驟(zou)。 3、如果數(shu)據中間有(you)連(lian)續的大于(yu)等于(yu)24個0,循環(huan)左移4的倍數(shu),使(shi)高(gao)位全為0。 4、找到高位的1,去掉前面大(da)偶(ou)數個(ge)0。 5、找到(dao)低位(wei)的1,去(qu)掉后面大偶數個0。 6、數(shu)剩(sheng)下的(de)位(wei)數(shu),如果(guo)小于等于8位(wei),那么這個數(shu)就(jiu)是立即(ji)數(shu),反之就(jiu)不是立即(ji)數(shu)。 針(zhen)對可(ke)能現的情況(kuang),我(wo)舉5個典型例子(zi): (1)0x4FF (2)0x122 (3)0x234 (4)0xF000000F (5)0x8000007F 例1: 0x4FF 第一(yi)步:0100 1111 1111 第二步(bu):其中(zhong)1的個(ge)數(shu)(shu)是(shi)9個(ge),大于8個(ge),判定不是(shi)立即(ji)數(shu)(shu) 例2: 0x122 第一步: 0001 0010 0010 第二步: 其中1的個數4個,小(xiao)于8,繼(ji)續 第三步: 其中沒(mei)有連續大(da)于等于24個0,繼續 第四部: xx01 0010 0010 (高位前面有3個0,大偶數2,去掉2個0) 第五步: xx10 0011 0010 (低位后面只有1個0,大偶數0) 第六部(bu): 剩(sheng)下(xia)10 0011 0010 共10位,大于8,判定0x122不是立(li)即(ji)數 例3: 0x234 第一(yi)步: 0010 0011 0100 第二步: 其中1的個數4個,小于8,繼續 第(di)三步(bu): 其中沒有連續大于(yu)等于(yu)24個0,繼續 第四部: xx10 0011 0100 第五步: xx10 0011 01xx 第六(liu)部: 剩下10 0011 01 共8位,等于(yu)8,判定(ding)0x234是立(li)即數(shu) 例4: 0xF000000F 第一步: 1111 0000 0000 0000 0000 0000 0000 1111 第二(er)步: 其(qi)中(zhong)1的個(ge)數(shu)8個(ge),沒(mei)有大于8,繼續(xu) 第三步: 其(qi)中(zhong)有連(lian)續24個0,循(xun)環左移4位,使高位全為(wei)0 0000 0000 0000 0000 0000 0000 0000 1111 1111 第四部: xxxx xxxx xxxx xxxx xxxx xxxx xxxx 1111 1111 第五步: xxxx xxxx xxxx xxxx xxxx xxxx xxxx 1111 1111 第(di)六部: 剩下1111 1111共8位,等于8,判定0xF000000F是立即(ji)數 例(li)5: 0x8000007F 第一步: 1000 0000 0000 0000 0000 0000 0111 1111 第二步: 其(qi)中1的個數8個,沒(mei)有大于8,繼續 第三步(bu): 其中有連(lian)續24個0,循環左移4位(wei),使(shi)高位(wei)全為(wei)0 0000 0000 0000 0000 0000 0000 0111 1111 1000 第四部(bu): xxxx xxxx xxxx xxxx xxxx xxxx 0111 1111 10xx 第(di)五(wu)步: xxxx xxxx xxxx xxxx xxxx xxxx 0111 1111 10xx 第六部: 剩下0111 1111 10共(gong)10位,等于(yu)8,判定(ding)0x7000008F是(shi)立即數(shu) 問題還沒有結束,我們在ARM匯編中(zhong)如(ru)何規避(bi)立(li)即(ji)數(shu)這(zhe)個問題呢,其實可以使用ARM匯編LDR偽指(zhi)令(ling),例如(ru)直接把MOV指(zhi)令(ling)變為, LDR R1,=0x12345678這(zhe)樣編譯器就不會(hui)報錯(cuo)(cuo)了。但這(zhe)種(zhong)方法也有弊端(duan)會(hui)增加開銷和影響(xiang)執行(xing)效(xiao)率。同時(shi)ARM匯編中(zhong)還有有效(xiao)數(shu)的概念,比如(ru) MOV R1,#0xFFFFFFFF 指(zhi)令(ling)中(zhong) 0xFFFFFFFF 不是(shi)(shi)(shi)(shi)立(li)即(ji)數(shu),但是(shi)(shi)(shi)(shi)是(shi)(shi)(shi)(shi)有效(xiao)數(shu),編譯器自動把原指(zhi)令(ling)變換(huan)為 MVN R1,#0,也不會(hui)報錯(cuo)(cuo)。有效(xiao)數(shu)判定:原數(shu)是(shi)(shi)(shi)(shi)立(li)即(ji)數(shu)或者原數(shu)反碼(ma)是(shi)(shi)(shi)(shi)立(li)即(ji)數(shu)。 相關資訊
發表評論
|