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

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > arm匯編中的跳轉(zhuǎn)指令

          arm匯編中的跳轉(zhuǎn)指令

          作者: 時間:2016-11-20 來源:網(wǎng)絡(luò) 收藏
          ARM匯編中,常有兩種跳轉(zhuǎn)方法:b跳轉(zhuǎn)指令、ldr指令向PC賦值。
          我自己經(jīng)過歸納如下:
          (1)b label
          該 指令完成的操作是pc<-label,將label處的地址傳給pc。b跳轉(zhuǎn)指令是相對跳轉(zhuǎn),依賴當前PC的值,偏移量是通過該指令本身的 bit[23:0]算出來的,這使得使用b指令的程序不依賴于要跳到的代碼的位置,只看指令本身。即該分支指令的二進制碼的后24位的實際的值是相對當前 的 R15 的值的一個偏移量;而不是一個絕對地址。它的值由匯編器來計算,它是 24 位有符號數(shù),左移兩位后有符號擴展為 32 位,表示的有效偏移為 26 位(+/- 32 M)。
          (2)ldr pc, =label
          該指令是一條偽指令,將內(nèi)存中的某個數(shù)據(jù)的位置(label處)賦給PC,同樣依賴當前PC的值,但是偏移量是那個位置(label)的連接地址(運行時的地址),所以可以用它實現(xiàn)從Flash到RAM的程序跳轉(zhuǎn),說白了,pc是個地址數(shù)值。
          偽指令LDR 常用于加載芯片外圍功能部件的寄存器地址(32 位立即數(shù)),以實現(xiàn)各種
          控制操作。
          如:ldr r0,=5e000000 ;將外圍某IO端口寄存器的地址賦給r0,注意該立即數(shù)前面沒有#。
          ---------------------------------------------------------------------------
          這里講一下為什么會有l(wèi)dr 偽指令

          范例demo.s:

          .equSTACK_BASE,0x0c002000

          .equSTACK_SIZE,0x00001000


          .text
          ldrsp,=STACK_BASE
          ldrsl,=STACK_BASE-STACK_SIZE
          ldrpc,=entry

          這是一個合法的匯編文件,它把堆棧基址設(shè)為0x0c002000,棧限設(shè)為0x0c001000,然后跳到entry所標識的C程序中執(zhí)行。

          下面我們假設(shè)符號“entry”的地址為0x0c000000。

          我們?nèi)绻焉厦娲a寫成:
          .text
          movsp,#0x0c002000
          movsl,#0x0c001000
          movpc,#0x0c000000
          匯編器會報錯:
          demo.s: Assembler messages:
          demo.s:2: Error: invalid constant -- `mov sp,#0x0c002000
          demo.s:3: Error: invalid constant -- `mov sl,#0x0c001000

          說起這個錯誤的原因可就話長了,簡而言之是因為RISC有一個重要的概念就是所有指令等長。在ARM指令集中,所有指令長度為4字節(jié)(Thumb指令是2 字節(jié))。那問題就來了,4字節(jié)是不可能同時存的下指令控制碼和32位立即數(shù)的,那么我要把一個32位立即數(shù)(比如一個32位地址值)傳送給寄存器該怎么 辦?
          RISC CPU提供一個通用的方法就是把地址值作為數(shù)據(jù)而不是代碼,從存儲器中相應(yīng)的位置讀入到寄存器中。像在代碼一中,將所有讀取的32位數(shù)據(jù)放到label標 注的內(nèi)存地址中,使用ldr偽指令,從該內(nèi)存處讀出該數(shù)據(jù)。因此label相當于一個內(nèi)存地址。如下,給出了代碼一的反匯編代碼:讓我們在Linux環(huán)境下執(zhí)行下面的命令:
          arm-elf-as -o demo.o demo.s
          arm-elf-objdump -D demo.o

          結(jié)果:
          demo.o:fileformatelf32-littlearm

          Disassemblyofsection.text:

          00000000<.text>:
          0: e59fd004 ldrsp,[pc,#4];c<.text+0xc>
          4: e59fa004 ldrsl,[pc,#4];10<.text+0x10>
          8: e59ff004 ldrpc,[pc,#4];14<.text+0x14>
          c: 0c002000 stceq0,cr2,[r0]
          10: 0c001000 stceq0,cr1,[r0]
          14:00000000 andeqr0,r0,r0
          Disassemblyofsection.data:

          0、4、8三行相當于是代碼段,C,10,14相當于是數(shù)據(jù)段,偽指令的變量定義存儲在這里。由于entry還沒連上目標地 址,objdump反匯編會認為是0,我們先不管它。另外兩條LDR偽指令變成了實際的LDR指令!但目標很奇怪,都是[pc, #4]。那好我們看看[pc, #4]是什么。
          我們知道pc中存放的是當前指令的下下條指令的位置,也就是.+8。那么上面的第一條指令ldrsp,[pc,#4]中的pc就是0x8,pc+4就是0xc,而[0xc]的內(nèi)容正是0x0c002000;同理,第二條ldr指令也是如此。顯然這里L(fēng)DR偽指令采用的是RISC通用的方法。
          另外從反匯編的代碼可以看出ldr偽指令中存儲的是一個相對偏移量,該偏移量是相對當前pc值的一個偏移量。
          ------------------------------------------------------------------------------
          (3)此外,有必要回味一下adr偽指令,U-boot中那段relocate代碼就是通過adr實現(xiàn)當前程序是在RAM中還是flash中。
          ADR指令為小范圍的地址讀取偽指令.ADR指令將基于PC相對偏移的地址值讀取到寄存器中.在匯編編譯源程序時,ADR偽指令被編譯器替換成一條合適的 指令.通常,編譯器用一條ADD指令或SUB指令來實現(xiàn)該ADR偽指令的功能,若不能用一條指令實現(xiàn),則產(chǎn)生錯誤,編譯失敗.
          ADR 偽指令格式如下
          ADR{cond} register,exper 其中
          register 加載的目標寄存器
          exper 地址表達式.當?shù)刂分凳欠亲值佚R時,取值范圍-255~255 字節(jié)之間;當?shù)刂肥亲謱R時,取值范圍-1020~1020 字節(jié)之間.對于基于PC 相對偏移的地址 值時,給定范圍是相對當前指令地址后兩個字處(因為ARM7TDMI 為三級流水線).
          ADR 偽指令舉例如下;
          LOOP MOV R1,#0xF0

          ADR R2,LOOP ;將LOOP 的地址放入R2
          ADR R3,LOOP+4
          可以用ADR 加載地址,實現(xiàn)查表:

          ADR R0,DISP_TAB ;加載轉(zhuǎn)換表地址
          LDRB R1,[R0,R2] ;使用R2 作為參數(shù),進行查表

          DISP_TAB
          DCB 0Xc0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90

          4 ldr pc,_label
          _label .word label
          一般ldr pc,=label就被解釋成上面這兩條指令,但是從反匯編程序中可以看出由于偏移量僅為4k,_label的定義位置要和ldr指令相距在4k以內(nèi)。借此可以實現(xiàn)大范圍地址的跳轉(zhuǎn),完成從flash到sdram的跳轉(zhuǎn)。


          關(guān)鍵詞: arm匯編跳轉(zhuǎn)指

          評論


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