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

          新聞中心

          EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 入門(mén)級(jí)ARM匯編指令

          入門(mén)級(jí)ARM匯編指令

          作者: 時(shí)間:2016-11-09 來(lái)源:網(wǎng)絡(luò) 收藏
          無(wú)論是體系結(jié)構(gòu)還是指令集,大家或多或少都應(yīng)該對(duì)X86匯編有些了解,而對(duì)于嵌入式領(lǐng)域已被廣泛采用的ARM 處理器,了解的可能并不多。如果你有興趣從事嵌入式方面的開(kāi)發(fā),那么了解一些RISC 體系結(jié)構(gòu)和ARM匯編的知識(shí)還是有必要的。這里,我們找出了這兩種體系結(jié)構(gòu)最明顯的不同之處,并對(duì)此進(jìn)行介紹,讓大家對(duì)于RISC體系結(jié)構(gòu)的匯編有一個(gè)基本的了解。首先,我們就來(lái)看一看基于RISC的ARM的體系結(jié)構(gòu)。

          基于RISC 的ARM CPU
          ARM是一種RISC體系結(jié)構(gòu)的處理器芯片。和傳統(tǒng)的CISC體系結(jié)構(gòu)不同,RISC 有以下的幾個(gè)特點(diǎn):
          ◆ 簡(jiǎn)潔的指令集——為了保證CPU可以在高時(shí)鐘頻率下單周期執(zhí)行指令,RISC指令集只提供很有限的操作(例如add,sub,mul等),而復(fù)雜的操作都需要由這些簡(jiǎn)單的指令來(lái)組合進(jìn)行模擬。并且,每一條指令不僅執(zhí)行時(shí)間固定,其指令長(zhǎng)度也是固定的,這樣,在譯碼階段就可以對(duì)下一條指令進(jìn)行預(yù)取。
          ◆ Load-Store 結(jié)構(gòu)——這個(gè)應(yīng)該是RISC 設(shè)計(jì)中比較有特點(diǎn)的一部分。在RISC 中,CPU并不會(huì)對(duì)內(nèi)存中的數(shù)據(jù)進(jìn)行操作,所有的計(jì)算都要求在寄存器中完成。而寄存器和內(nèi)存的通信則由單獨(dú)的指令來(lái)完成。而在CSIC中,CPU是可以直接對(duì)內(nèi)存進(jìn)行操作的,這也是一個(gè)比較特別的地方。
          ◆ 更多的寄存器——和CISC 相比,基于RISC的處理器有更多的通用寄存器可以使用,且每個(gè)寄存器都可以進(jìn)行數(shù)據(jù)存儲(chǔ)或者尋址。
          當(dāng)然,作為RISC 領(lǐng)域最成功的處理器,ARM也遵從上面的特點(diǎn)。這里,我們不妨來(lái)看一看在user 模式下,ARM處理器的體系結(jié)構(gòu),這對(duì)于我們了解其匯編語(yǔ)言是有好處的。而其它模式下只是有一些寄存器分組略有不同,大家可以在ARM的手冊(cè)上查到。這里要說(shuō)明的是,盡管ARM處理器也支持16位指令,不過(guò)在下文中,我們都假定ARM處理器在32 位模式下工作。


          圖1:user模式下ARM處理器體系結(jié)構(gòu)
          從圖1中我們看到,在user 模式下,ARM CPU 有16個(gè)數(shù)據(jù)寄存器,被命名為r0~r15(這個(gè)要比x86的多一些)。r13~r15有特殊用途,其中:
          ◆ r13 - 指向當(dāng)前棧頂,相當(dāng)于x86的esp,這個(gè)東西在匯編指令中要用sp 表示
          ◆ r14 - 稱作鏈接寄存器,指向函數(shù)的返回地址。用lr表示,這和x86將返回地址保存在棧中是不同的
          ◆ r15 - 類似于x86的eip,其值等于當(dāng)前正在執(zhí)行的指令的地址+8(因?yàn)樵谌≈泛蛨?zhí)行之間多了一個(gè)譯碼的階段),這個(gè)用pc表示
          另外,ARM處理器還有一個(gè)名為cspr的寄存器,用來(lái)監(jiān)視和控制內(nèi)部操作,這點(diǎn)和x86 的狀態(tài)寄存器是類似的。具體的內(nèi)容就用到再說(shuō)了。

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

          ARM 指令集
          ARM處理器可以支持3種指令集——ARM,Thumb和Jazelle。
          采用那種指令集,由cspr中的標(biāo)志位來(lái)決定。大體說(shuō)來(lái):
          ◆ ARM——這是ARM自身的32 位指令集
          ◆ Thumb ——這是一個(gè)全16 位的指令集,在16 位外部數(shù)據(jù)總線寬度下,這個(gè)指令集的效率要比32 位的ARM指令高一些。
          ◆ Jazelle ——這是一個(gè)8位指令集,用來(lái)加速Java字節(jié)碼的執(zhí)行
          整個(gè)ARM指令集由數(shù)據(jù)處理指令、分支指令、Load-Store指令、程序中斷指令和一些系統(tǒng)控制指令構(gòu)成,除了Load-Store指令外,其他部分和x86指令集是比較類似的。但和x86相比,ARM指令最顯著的特點(diǎn)它們都是32-bit 定長(zhǎng)的。另外,由于arm是基于RISC指令集的,所以CPU只處理在寄存器中的數(shù)據(jù)并通過(guò)獨(dú)立的load-store指令在內(nèi)存和寄存器之間進(jìn)行數(shù)據(jù)的傳遞。
          在使用方面,ARM指令的格式也要比Intel的復(fù)雜些。一般說(shuō)來(lái),一條ARM指令有如下的形式:
          {S} [Rd], [Rn], [Rm]
          其中:
          * {S} —— 加上這個(gè)后綴的指令會(huì)更新cpsr 寄存器
          * [Rd] —— 目的寄存器
          * [Rn]/[Rm] —— 源寄存器
          一般來(lái)說(shuō),arm 指令有3個(gè)操作數(shù),其中Rm寄存器在執(zhí)行指令前可以進(jìn)入桶形移位器進(jìn)行移位操作,而Rn則會(huì)直接進(jìn)入ALU 單元。如果一條arm 指令只有2 個(gè)操作數(shù),那么源寄存器按照Rm 來(lái)處理。例如,一條加法指令:
          add r0, r1, #1
          就會(huì)把r1+1的結(jié)果存放到r0中。
          在熟悉了基本的匯編格式后,讀者就可以自行去查詢基本的ARM匯編指令了,下面,我們找出ARM中比較有特色部分——Load-Store指令結(jié)構(gòu),它是CPU 和內(nèi)存進(jìn)行通信的一個(gè)重要媒介。

          Load-Store 指令體系
          由于ARM CPU并不直接處理內(nèi)存中的數(shù)據(jù),這個(gè)指令體系就擔(dān)起了在寄存器和內(nèi)存之間交換數(shù)據(jù)的重要媒介。它要比x86 的內(nèi)存訪問(wèn)機(jī)制復(fù)雜一些。該指令體系分成3 類:
          ◆ 單寄存器傳輸(這是與x86 最為相像的)
          ◆ 多寄存器傳輸
          ◆ 交換指令

          單寄存器傳輸
          先看第一個(gè),很簡(jiǎn)單:把單一的數(shù)據(jù)傳入(LDR) 或傳出(STR)寄存器,對(duì)內(nèi)存的訪問(wèn)可以是DWORD(32-bit), WORD(16-bit)和BYTE(8-bit)。指令的格式如下:
          DWORD:
          Rd, addressing1
          WORD:
          H Rd, addressing2 無(wú)符號(hào)版
          SH Rd, addressing2 有符號(hào)版
          BYTE:
          B Rd, addressing1 無(wú)符號(hào)版
          SB Rd, addressing2 有符號(hào)版
          addressing1 和addressing2 的分類下面再說(shuō),現(xiàn)在理解成某種尋址方式就可以了。
          在單寄存器傳輸方面,還有以下三種變址模式,他們是:
          ◆ preindex
          這種變址方式和x86的尋址機(jī)制是很類似的,先對(duì)寄存器進(jìn)行運(yùn)算,然后尋址,但是在尋之后,基址寄存器的內(nèi)容并不發(fā)生改變,例如:
          ldr r0, [r1, #4]
          的含義就是把r1+4 這個(gè)地址處的DOWRD 加載到r0,而尋址后,r1 的內(nèi)容并不改變。
          ◆ preindex with writeback
          這種變址方式有點(diǎn)類似于++i的含義,尋址前先對(duì)基地址寄存器進(jìn)行運(yùn)算,然后尋址. 其基本的語(yǔ)法是在尋址符[]后面加上一個(gè)"!" 來(lái)表示.例如:
          ldr r0, [r1, #4]!
          就可以分解成:
          add r1, r1, #4
          ldr r0, [r1, #0]
          ◆ postindex
          自然這種變址方式和i++的方式就很類似了,先利用基址寄存器進(jìn)行尋址,然后對(duì)基址寄存器進(jìn)行運(yùn)算,其基本語(yǔ)法是把offset 部分放到[]外面,例如:
          ldr r0, [r1], #4
          就可以分解成:
          ldr r0, [r1, #0]
          add r1, r1, #4
          如果你還記得x86 的SIB 操作的話,那么你一定想ARM是否也有,答案是有也沒(méi)有。在ss上面提到的addressing1 和addressing2的區(qū)別就是比例寄存器的使用,addressing1可以使用[base, scale, 桶形移位器]來(lái)實(shí)現(xiàn)SB 的效果,或者通過(guò)[base,offset](這里的offset 可以是立即數(shù)或者寄存器)來(lái)實(shí)現(xiàn)SI 的效果,而addressing2則只能用后者了。于是每一種變址方式最多可以有3 種尋址方式,這樣一來(lái),最多可以有9種用來(lái)尋址的指令形式。例如:
          ldr r0, [r1, r2, LSR #0x04]!
          ldr r0, [r1, -#0x04]
          ldr r0, [r1], LSR #0x04
          每樣找了一種,大概就是這個(gè)意思。到此,單寄存器傳輸就結(jié)束了,掌握這些足夠應(yīng)付差事了。下面來(lái)看看多寄存器傳輸吧。

          多寄存器傳輸
          說(shuō)得很明白,意思就是通過(guò)一條指令同時(shí)把多個(gè)寄存器的內(nèi)容寫(xiě)到內(nèi)存或者從內(nèi)存把數(shù)據(jù)寫(xiě)到寄存器中,效率高的代價(jià)是會(huì)增加系統(tǒng)的延遲,所以armcc 提供了一個(gè)編譯器選項(xiàng)來(lái)控制寄存器的個(gè)數(shù)。指令的格式有些復(fù)雜:
          <尋址模式> Rn{!}, {r^}
          我們先來(lái)搞明白尋址模式,多寄存器傳輸模式有4 種:
          也就是說(shuō)以A開(kāi)頭的都是在Rn的原地開(kāi)始操作,而B(niǎo)開(kāi)頭的都是以Rn的下一個(gè)位置開(kāi)始操作。如果你仍然感到困惑,我們不妨看個(gè)例子。
          所有的示例指令執(zhí)行前:
          mem32[0x1000C] = 0x04
          mem32[0x10008] = 0x03
          mem32[0x10004] = 0x02
          mem32[0x10000] = 0x01
          r0 = 0x00010010
          r1 = 0x00000000
          r3 = 0x00000000
          r4 = 0x00000000
          1) ldmia r0!, {r1-r3} 2) ldmib r0!, {r1-r3}
          執(zhí)行后: 執(zhí)行后:
          r0 = 0x0010001C r0 = 0x0010001C
          r1 = 0x01 r1 = 0x02
          r2 = 0x02 r2 = 0x03
          r3 = 0x03 r3 = 0x04
          至于DA 和DB 的模式,和IA / IB 是類似的,不多說(shuō)了。
          最后要說(shuō)的是,使用ldm 和stm指令對(duì)進(jìn)行寄存器組的保護(hù)是很常見(jiàn)和有效的功能。配對(duì)方案:
          stmia / ldmdb
          stmib / ldmda
          stmda / ldmib
          stmdb / ldmia
          繼續(xù)來(lái)看兩個(gè)例子:
          執(zhí)行前:
          r0 = 0x00001000
          r1 = 0x00000003
          r2 = 0x00000002
          r3 = 0x00000001
          執(zhí)行的指令:
          stmib r0!, {r1-r3}
          mov r1, #1 ; These regs have been modified
          mov r2, #2
          mov r3, #3
          當(dāng)前寄存器狀態(tài):
          r0 = 0x0000100C
          r1 = 0x00000001
          r2 = 0x00000002
          r3 = 0x00000003
          ldmia r0!, {r1-r3}
          最后的結(jié)果:
          r0 = 0x00001000
          r1 = 0x00000003
          r2 = 0x00000002
          r3 = 0x00000001
          另外,我們還可以利用這個(gè)指令對(duì)完成內(nèi)存塊的高效copy:
          loop
          ldmia r9!, {r0-r7}
          stmia r10!, {r0-r7}
          cmp r9, r11
          bne loop
          說(shuō)到這里,讀者應(yīng)該對(duì)RISC的Load-Store體系結(jié)構(gòu)有一個(gè)大概的了解了,能夠正確配對(duì)使用指令,是很重要的。



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