<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匯編中的跳轉(zhuǎn)指令

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

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

          范例demo.s:

          .equSTACK_BASE,0x0c002000

          .equSTACK_SIZE,0x00001000


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

          這是一個(gè)合法的匯編文件,它把堆?;吩O(shè)為0x0c002000,棧限設(shè)為0x0c001000,然后跳到entry所標(biāo)識(shí)的C程序中執(zhí)行。

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

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

          說(shuō)起這個(gè)錯(cuò)誤的原因可就話長(zhǎng)了,簡(jiǎn)而言之是因?yàn)镽ISC有一個(gè)重要的概念就是所有指令等長(zhǎng)。在ARM指令集中,所有指令長(zhǎng)度為4字節(jié)(Thumb指令是2 字節(jié))。那問(wèn)題就來(lái)了,4字節(jié)是不可能同時(shí)存的下指令控制碼和32位立即數(shù)的,那么我要把一個(gè)32位立即數(shù)(比如一個(gè)32位地址值)傳送給寄存器該怎么 辦?
          RISC CPU提供一個(gè)通用的方法就是把地址值作為數(shù)據(jù)而不是代碼,從存儲(chǔ)器中相應(yīng)的位置讀入到寄存器中。像在代碼一中,將所有讀取的32位數(shù)據(jù)放到label標(biāo) 注的內(nèi)存地址中,使用ldr偽指令,從該內(nèi)存處讀出該數(shù)據(jù)。因此label相當(dāng)于一個(gè)內(nèi)存地址。如下,給出了代碼一的反匯編代碼:讓我們?cè)贚inux環(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三行相當(dāng)于是代碼段,C,10,14相當(dāng)于是數(shù)據(jù)段,偽指令的變量定義存儲(chǔ)在這里。由于entry還沒(méi)連上目標(biāo)地 址,objdump反匯編會(huì)認(rèn)為是0,我們先不管它。另外兩條LDR偽指令變成了實(shí)際的LDR指令!但目標(biāo)很奇怪,都是[pc, #4]。那好我們看看[pc, #4]是什么。
          我們知道pc中存放的是當(dāng)前指令的下下條指令的位置,也就是.+8。那么上面的第一條指令ldrsp,[pc,#4]中的pc就是0x8,pc+4就是0xc,而[0xc]的內(nèi)容正是0x0c002000;同理,第二條ldr指令也是如此。顯然這里L(fēng)DR偽指令采用的是RISC通用的方法。
          另外從反匯編的代碼可以看出ldr偽指令中存儲(chǔ)的是一個(gè)相對(duì)偏移量,該偏移量是相對(duì)當(dāng)前pc值的一個(gè)偏移量。
          ------------------------------------------------------------------------------
          (3)此外,有必要回味一下adr偽指令,U-boot中那段relocate代碼就是通過(guò)adr實(shí)現(xiàn)當(dāng)前程序是在RAM中還是flash中。
          ADR指令為小范圍的地址讀取偽指令.ADR指令將基于PC相對(duì)偏移的地址值讀取到寄存器中.在匯編編譯源程序時(shí),ADR偽指令被編譯器替換成一條合適的 指令.通常,編譯器用一條ADD指令或SUB指令來(lái)實(shí)現(xiàn)該ADR偽指令的功能,若不能用一條指令實(shí)現(xiàn),則產(chǎn)生錯(cuò)誤,編譯失敗.
          ADR 偽指令格式如下
          ADR{cond} register,exper 其中
          register 加載的目標(biāo)寄存器
          exper 地址表達(dá)式.當(dāng)?shù)刂分凳欠亲值佚R時(shí),取值范圍-255~255 字節(jié)之間;當(dāng)?shù)刂肥亲謱?duì)齊時(shí),取值范圍-1020~1020 字節(jié)之間.對(duì)于基于PC 相對(duì)偏移的地址 值時(shí),給定范圍是相對(duì)當(dāng)前指令地址后兩個(gè)字處(因?yàn)锳RM7TDMI 為三級(jí)流水線).
          ADR 偽指令舉例如下;
          LOOP MOV R1,#0xF0

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

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

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

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


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

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