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

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > ARM匯編編程基礎(chǔ)之六-其它尋址模式與其它指令

          ARM匯編編程基礎(chǔ)之六-其它尋址模式與其它指令

          作者: 時間:2016-11-27 來源:網(wǎng)絡(luò) 收藏
          現(xiàn)在我們已經(jīng)掌握了所有知識,可以編寫簡單的ARM匯編程序,但如果要編寫較為復(fù)雜的ARM程序,就必須掌握更多的尋址模式和指令,這就是本文的重點所在。

          我們在“基本尋址模式與基本指令”一文中學(xué)習(xí)了最常用的3種尋址方式。下面介紹其它尋址方式。

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

          1、基址尋址

          基址尋址就是將基址寄存器的內(nèi)容與指令中給出的偏移量相加,形成操作數(shù)的有效地址。基址尋址用于訪問基址附近的存儲單元,常用于查表、數(shù)組操作、功能部件寄存器訪問等?;穼ぶ分噶钆e例如下:

          LDR R1,[R2,#0x0C]

          R2的值+0x0C形成內(nèi)存地址,讀取內(nèi)存中該地址上的內(nèi)容,放入R1

          其它額外需要了解的內(nèi)容:

          §零偏移。 如:LDR R0,[R1]

          §前索引偏移。 如:LDR R0,[R1,#0x04]!,表示將R1的值加上4后作為內(nèi)存地址,并且指令執(zhí)行結(jié)束時,R1本身的值也要加4。這里!表示要回寫

          §程序相對偏移。 如:LDR R0,labe1,表示將標(biāo)號label所代表的地址處存放的內(nèi)容放入R0,相當(dāng)于LDR R0, [PC, #某個常數(shù)]

          §后索引偏移。 如:LDR R0,[R1],#0x04,表示將R1的值作為內(nèi)存地址,并且指令執(zhí)行結(jié)束時,R1本身的值要加4

          2、多寄存器尋址

          多寄存器尋址一次可傳送幾個寄存器值,允許一條指令傳送16個寄存器的任何子集或所有寄存器。多寄存器尋址指令舉例如下:

          LDMIA R1!,{R2-R4,R6} ,它是ldr的多寄存版本,將內(nèi)存中的4個字放入寄存器R2,R3,R4,R6中

          指令執(zhí)行前指令執(zhí)行后

          兩點說明:

          1)、R1!中的!號表示在指令執(zhí)行完成后,要改變(回寫)基址寄存器(R1)的值

          2)、寄存器列表{R2-R4, R6}中的順序并不要緊。最終寄存器與內(nèi)存地址的對應(yīng)關(guān)系是:編號小的寄存器與內(nèi)存的低地址相對應(yīng)

          兩點問題:

          1)、為什么內(nèi)存起地址是0x40000000,而不是0x40000004

          2)、為什么內(nèi)存地址是從0x40000000 ---- 0x4000000C,而不是從0x3FFFFFF4 ----0x40000000

          要解釋上面2個問題,其實也很簡單。其實多寄存加載指令ldm總共有4個:ldmia、 ldmib、 ldmda、 ldmdb。ia的意思是increase after,ib的意思是increase before,da的意思是decrease after,db的意思是decrease before。以LDMIA R1!, {R2-R4, R6}為例子,這里的ia是指辦事(將內(nèi)存中的數(shù)加載到寄存器)之后增加基址寄存器(R1)的值。這條指令的執(zhí)行過程從邏輯上看,如下:

          1)、先辦事:將R1的值(0x40000000)作為內(nèi)存地址,到該地址處取得數(shù)(0x01),加載到寄存器R2中

          2)、后增加:將R1的值從0x40000000增加為0x40000004

          再重復(fù)上面的操作3次,分別將內(nèi)存中的數(shù)0x02、0x03、0x04放到寄存器中R3、R4、R6中,最后R1的值變?yōu)?x40000010。

          這個例子中,如果將ldmia改為ldmib,則R2、R3、R4、R6中存放的是0x02、0x03、0x04、內(nèi)存0x40000010處的內(nèi)容,最后R1的值為0x40000010。

          除了4條多寄存器加載指令外,還有4條類似的多寄存器存儲指令,分別是stria、 strib、 strda、 strdb

          3、堆棧尋址

          由于ARM指令集沒有專門的出棧和入棧指令,所以ARM匯編程序是采用SP作為棧指針,以stm指令完成入棧操作,以ldm指令完成出棧操作。

          以入棧后SP的值是增加還是減少為依據(jù),可將堆棧類型劃分為遞增堆棧(向上生長)和遞減堆棧(向下生長);

          以SP所指向的內(nèi)存處存放的是棧頂元素還是下一次要入棧的元素,可將堆棧類型劃分為滿堆棧和空堆棧

          那么當(dāng)堆棧類型為空遞減堆棧時候,入棧操作應(yīng)該使用什么指令?出棧操作應(yīng)該使用什么指令?進一步,如果堆棧類型為空遞增、滿遞增、滿遞減堆棧,又將如何呢?如果你不看下面的答案,我相信你一定會讓這幾個問題折磨得做很多的腦力體操,然后感嘆ARM指令集的設(shè)計者太不為你這樣的程序員考慮了,給了你本不應(yīng)該由你承擔(dān)的負(fù)荷。但事實上正相反,ARM指令集的設(shè)計者充分理解了你作為程序員的苦惱,請看下面的答案。

          數(shù)據(jù)塊傳送堆棧操作說明
          存儲壓棧
          STMDASTMED空遞減
          STMIASTMEA空遞增
          STMDBSTMFD滿遞減
          STMIBSTMFA滿遞增
          數(shù)據(jù)塊傳送堆棧操作說明
          加載出棧
          LDMDALDMFA滿遞增
          LDMIALDMFD滿遞減
          LDMDBLDMEA空遞增
          LDMIBLDMED空遞減

          這2張表的第一、三列回答了前面你絞盡腦汁回答的問題。而第二列則體現(xiàn)了ARM指令集的設(shè)計者對作為程序員的你的充分體貼。第二列中的ED、EA、FD、FA分別表示empty descend(空遞減)、 empty ascend(空遞增)、 full descend(滿遞減)、 full ascend(滿遞增),其含義是說,如果你采用的是空遞減(空遞增、滿遞減、滿遞增)堆棧的話,入棧操作則使用指令STMED(STMEA、STMFD、STMFA),出棧操作則使用指令LDMED(LDMEA、LDMFD、LDMFA)。從此你再也不會為你應(yīng)該使用ia、ib、da還是db來實現(xiàn)出、入棧操作而苦惱了。


          上一頁 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); })();