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

          新聞中心

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

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

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

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

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

          1、基址尋址

          基址尋址就是將基址寄存器的內(nèi)容與指令中給出的偏移量相加,形成操作數(shù)的有效地址?;穼ぶ酚糜谠L(fǎng)問(wèn)基址附近的存儲(chǔ)單元,常用于查表、數(shù)組操作、功能部件寄存器訪(fǎng)問(wèn)等?;穼ぶ分噶钆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é)束時(shí),R1本身的值也要加4。這里!表示要回寫(xiě)

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

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

          2、多寄存器尋址

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

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

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

          兩點(diǎn)說(shuō)明:

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

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

          兩點(diǎn)問(wèn)題:

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

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

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

          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。

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

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

          3、堆棧尋址

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

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

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

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

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

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


          上一頁(yè) 1 2 下一頁(yè)

          關(guān)鍵詞: ARM匯編編程尋址模

          評(píng)論


          技術(shù)專(zhuān)區(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); })();