<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > ARM的常數(shù)表達(dá)式

          ARM的常數(shù)表達(dá)式

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


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


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


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


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


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


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


          關(guān)鍵詞: ARM常數(shù)表達(dá)

          評(píng)論


          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();