新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > ARM的常數表達式

        ARM的常數表達式

        作者: 時間:2016-11-20 來源:網絡 收藏
        如果說Intel指令中的立即數,相信大家都很熟悉。類似的,Arm指令中的“立即數”就是常數表達式。之所以稱為常數表達式,而不稱為立即數是有原因的。
        Intel指令屬于CISC指令集,指令是不定長的,因此可以將任意32位立即數編碼到指令內。


        Arm指令屬于RISC指令集,指令是定長的32字節。眾所周知,指令中操作碼是必須的字段,如果把32位立即數直接編碼到指令內部,操作碼就無“容身之地”了……


        因此,Arm指令中“立即數”的位數必小于32位。那么如何在Arm指令中正常表示立即數呢?我們看看Arm的通用指令格式。


        Arm指令中,操作碼(opcode)、目的操作數(Rd)、源操作數1(Rn)是必須的字段。條件碼(cond)、符號位標記(s)源操作數2(oprand2)是可選的。其中Rd和Rn必須是寄存器,因此Arm的“立即數”只能存儲在oprand2。


        在Arm的指令編碼內,使用“立即數”的指令為“立即數”提供了12bit的存儲空間,也就是說Arm的“立即數”只能表示212=4096個數字。這顯然無法表示所有的32位立即數,如果使用這12bit表示0~4095的數字,那么從4096~(232-1)的數組都不能表示了。考慮到這種“后果”,Arm指令集的設計者們使用了一個技巧,即使用常數表達式代替立即數的概念。
        常數表達式表示一個常數,且該常數對應8位的位圖,即可以由一個8位的常數通過循環移位偶數位得到。


        比如0x3fc可以由8位常數0xff循環左移2位或循環右移30位得到,是常數表達式。再比如0x1fe,雖然可以有0xff循環左移1位或循環右移31位得到,但是移動的位數不是偶數,因此不是常數表達式。
        根據常數表達式的定義,常數表達式只需要12bit的存儲空間。


        12bit空間中,低8字節存儲8位位圖,高4字節存儲循環右移的次數。4字節只能表示24=16種移動次數,但是由于常數表達式定義中,移位限定為偶數次,因此這4個字節剛好能表示0、2、4、6、8…32位16個數字!
        比如0x3fc的二進制表示為0xfff,即使用8位數字0xff循環右移0xf*2=30次得到。
        明確了常數表達式的含義后,可以通過簡單的編程識別一個數字是否是常數表達式。
        /*
        循環左移兩位
        */
        void roundLeftShiftTwoBit(unsigned int& num)
        {
        unsigned int overFlow=num & 0xc0;//取左移即將溢出的兩位
        num=(num<<2) (overFlow>>30);//將溢出部分追加到尾部
        }
        /*
        判斷num是否是常數表達式,8位數字循環右移偶數位得到
        */
        bool constExpr(unsigned int num)
        {
        for(int i=0;i<16;i++){
        if(num<=0xff)
        return true;//有效位圖
        else
        roundLeftShiftTwoBit(num);//循環左移2位
        }
        }
        roundLeftShiftTwoBit函數將一個無符號32位整數循環左移2位,constExpr反復將一個無符號32位整數循環左移2位,直到發現該數字在0到0xff之間為止,否則表示該數字不是常數表達式。
        通過常數表達式,Arm指令便避免了“立即數”僅僅局限于0~4095的數字范圍的問題了。但是常數表達式仍不能表示全部的32位整數,比如0x1fe。對于非常數表達式的數字,只能通過拆分來解決。
        比如Arm指令mov r0,#0x1fe不是合法的指令,因為0x1fe不是常數表達式。那么只能將0x1fe拆分,表示為兩條指令,比如:
        mov r0,#0xfe
        add r0,r0,#0x100
        除了拆分數字的方法,Arm的LDR宏使用臨時變量的方式實現非常數表達式的數據傳送,即:
        LDR r0,=0x1fe
        ldr宏指令不是Arm的真正指令,它由如下兩條指令實現:
        .tmp .word 0x1fe
        ldr r0,.tmp
        ldr r0,[r0]
        Arm的ldr指令用于將內存的數據加載到寄存器。這里數字0x1fe被存儲在ldr指令附近的位置.tmp處,ldr r0,.tmp被編譯為ldr r0,[pc+offset]的形式,其中offset為符號.tmp相對ldr指令的偏移。這樣ldr r0,.tmp獲取了符號.tmp的地址,然后再次使用ldr r0,[r0]將.tmp地址處的數據取出,即0x1fe。
        通過以上的描述,我們明確了Arm指令中常數表達式的真正含義,并基于此編寫了一個驗證常數表達式的函數。最后,我們解析了如何在Arm中實現非常數表達式數據的傳送,并討論了它的實現。希望對你理解Arm的常數表達式有所幫助。


        關鍵詞: ARM常數表達

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 新竹市| 铁岭市| 玉树县| 深圳市| 无极县| 新建县| 蒲江县| 古蔺县| 明星| 二手房| 龙泉市| 凭祥市| 安阳市| 北京市| 石首市| 达孜县| 锡林浩特市| 特克斯县| 东乌珠穆沁旗| 托克逊县| 焉耆| 义乌市| 嘉鱼县| 南通市| 玛纳斯县| 南和县| 武鸣县| 凤翔县| 浦城县| 壤塘县| 桦南县| 甘肃省| 苍山县| 蓬溪县| 准格尔旗| 广南县| 女性| 宁海县| 祁阳县| 丹寨县| 乃东县|