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

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > ARM編程進階之一-ARM匯編偽指令

          ARM編程進階之一-ARM匯編偽指令

          作者: 時間:2016-11-27 來源:網(wǎng)絡 收藏
          到目前為止,我們已經(jīng)具備編寫較為復雜的ARM匯編程序的能力,但要編寫較為復雜且實用的程序,我們就不得不掌握ARM匯編的偽指令(pseudo-instruction)。千萬別把匯編偽操作(directive)與匯編偽指令(pseudo-instruction)弄混了,directive不會被編譯器編譯為機器指令,但pseudo-instruction會。而pseudo-instruction與指令(instruction)的區(qū)別在于,1條instruction與1條機器指令對應,而編譯器會把1條pseudo-instruction編譯為1條或多條機器指令。

          ARM匯編偽指令共4條:ldr、adr、adrl、nop

          本文引用地址:http://www.ex-cimer.com/article/201611/322178.htm

          1、ldr

          首先我們來回答“基本尋址模式與基本指令”一文中提出的問題。“如果我們需要mov r0, #10000這樣的指令,應該怎么辦?(常數(shù)10000不能在機器指令32bit中的低12bit中被表示出來)”。當你進行編譯的時候,“Error:All70E”的錯誤就會出現(xiàn),如下圖。

          其實,這個問題很容易解決,只需要將mov r0, #10000換為ldr r0, =10000即可。為什么這樣就可以了呢?因為,這里的ldr r0, =10000并非我們已經(jīng)學過的ldr指令,而是一條偽指令,編譯器會將這條偽指令替換為:

          ldr r0, [pc, #-4]
          DCD 10000

          DCD所分配的內(nèi)存空間中存放了整數(shù)10000,該內(nèi)存空間被稱為literal pool,中文名稱“文字池”。由于整個程序都是由編譯器編譯的(包括文字池的分配),所以很顯然編譯器能夠知道ldr指令在內(nèi)存中的地址與文字池在內(nèi)存中的位置之間的偏移量,因此編譯器就可以正確地使用以pc為基址,采用相對尋址的ldr指令將文字池中的數(shù)取出加載到寄存器r0中。由此可見,編譯器對于ldr r0, =10000這條偽指令的處理,其實質(zhì)是:

          在匯編源程序時,LDR偽指令被編譯器替換成一條合適的指令和存放常數(shù)的文字池。匯編器將常量放入文字池,并使用一條程序相對偏移的LDR指令從文字池讀出常量。

          由于,4byte可以存放任何int型整數(shù),這樣一來,常數(shù)就可以是任何int型整數(shù),而不再受制于12bit的限制。當然此時的常數(shù)是存放在內(nèi)存中的,而不是存放在機器指令的32bit編碼中的。

          額外說明:

          a)、ldr r0, [pc, #-4]中是-4,而不是+4,是由于流水線的原因(參見“流水線對PC值的影響”一文)。今后對于流水線的這種影響,我將不再予以特別說明。

          b)、從指令位置到文字池的偏移量必須小于4KB

          c)、從語法上來看,與ARM指令的LDR相比,偽指令LDR的參數(shù)有“=”號,沒有“#”號

          d)、如果常數(shù)能夠被12bit表示出來,例如:ldr r0, =0x100,那么,編譯器對該偽指令的處理,是使用MOV(或者MVN)指令代替該LDR偽指令,例如:mov r0, #0x100,而不會采用ldr指令+文字池的方式。

          除了 ldr 寄存器, =常數(shù) 這種形式外,還有l(wèi)dr 寄存器, =標號 這種形式也經(jīng)常被使用,下面我就來講解這種形式的ldr偽指令。

          由上圖可見:ldr pc, =InitStack這條偽指令的作用是將標號InitStack所代表的地址賦予pc。 這里會使我們產(chǎn)生幾個疑問:

          a)、為什么不使用bl InitStack,而要使用ldr pc, =InitStack?

          這是因為bl指令的跳轉(zhuǎn)范圍是正負32M,而InitStack所代表的位置有可能距離ldr pc, =InitStack超過32M,此時bl就無能為力了。竟然存在這么大范圍跳轉(zhuǎn)的程序(這似乎意味著編譯出來的二進制可執(zhí)行文件的大小會操作32M),這一點似乎令我們感到非常震驚。事實上是:大小超過32M的可執(zhí)行程序的確幾乎不可能出現(xiàn),但即使是很小的二進制程序中也可能進行大范圍(超過32M)的跳轉(zhuǎn),這一點在bootloader程序中幾乎是必然的。


          上一頁 1 2 下一頁

          關(guān)鍵詞: ARM編程進階匯編偽指

          評論


          技術(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); })();