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

          新聞中心

          EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > Thumb指令集之: ARM和Thumb的混合編程

          Thumb指令集之: ARM和Thumb的混合編程

          作者: 時(shí)間:2013-09-30 來(lái)源:網(wǎng)絡(luò) 收藏

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

          在實(shí)現(xiàn)代碼和Thumb代碼轉(zhuǎn)換時(shí),大部分的指令有等價(jià)的Thumb指令,只有少數(shù)指令沒(méi)有。如加載字節(jié)指令(LDR)不支持自動(dòng)變址,軟中斷指令不能條件執(zhí)行。

          在編寫Thumb代碼時(shí)要注意以下幾點(diǎn)。

          ①匯編器需要知道什么時(shí)候產(chǎn)生代碼、什么時(shí)候產(chǎn)生Thumb代碼,程序中使用CODE32和CODE16偽操作提供給編譯器這些信息。

          ②由于處理器上電執(zhí)行是在ARM狀態(tài)下完成的,所以要使用Thumb指令必須由ARM指令調(diào)用Thumb指令,這一過(guò)程是通過(guò)“BXLR”指令來(lái)實(shí)現(xiàn)的。需要注意的是,在使用“BXLR”指令前,要對(duì)寄存器LR做正確的初始化。

          ③在ARM和Thumb時(shí),常使用ALIGN偽操作保證內(nèi)存地址對(duì)齊。

          11.10.2互交子程序

          編寫ARM/Thumb互交代碼時(shí),下面兩點(diǎn)需要注意。

          ①對(duì)于C/C++子程序而言,只要在編譯時(shí)指定--apcs/interwork選項(xiàng),匯編器會(huì)生成合適的返回代碼,使得程序返回到和調(diào)用程序相同的狀態(tài)。

          ②在匯編語(yǔ)言子程序中,用戶必須自己編寫相應(yīng)的返回代碼,使得程序返回到和調(diào)用程序相同的狀態(tài)。

          如果目標(biāo)代碼包含以下內(nèi)容,應(yīng)該在編譯或匯編時(shí)使用--apcs/interwork選項(xiàng)使處理器能夠在ARM和Thumb代碼間進(jìn)行正確的切換,這種情況包含以下4種。

          ①需要返回到ARM狀態(tài)的Thumb子程序。

          ②需要返回到Thumb狀態(tài)的ARM子程序。

          ③間接調(diào)用ARM子程序的Thumb子程序。

          ④間接調(diào)用Thumb子程序的ARM子程序。

          如果在程序連接階段,連接器發(fā)現(xiàn)ARM子程序和Thumb子程序間存在相互調(diào)用,而源文件在編譯時(shí)沒(méi)有使用--apcs/interwork選項(xiàng),則連接器將報(bào)告以下錯(cuò)誤。

          Error:L6239E:CannotcallARMsymbol'arm_function'innon-interworkingobject

          armsub.ofromTHUMBcodeinthumbmain.o(.text)

          其中,“arm_function”為需要進(jìn)行狀態(tài)切換的子程序名。

          在這種情況下,用戶必須使用--apcs/interwork選項(xiàng)重新對(duì)源文件進(jìn)行編譯。

          但在下面兩種情況下,不必指定--apcs/interwork選項(xiàng)。

          ①在Thumb狀態(tài)下,發(fā)生異常中斷時(shí),處理器自動(dòng)切換到ARM狀態(tài),這時(shí)不需要添加狀態(tài)切換代碼。

          ②當(dāng)異常發(fā)生在Thumb狀態(tài)時(shí),從異常返回不需要添加狀態(tài)切換的代碼。

          1.使用匯編語(yǔ)言實(shí)現(xiàn)互交

          對(duì)于匯編程序來(lái)說(shuō),可以有兩種方法來(lái)實(shí)現(xiàn)程序狀態(tài)的切換。第一種方法是利用連接器提供的交互子程序來(lái)實(shí)現(xiàn)程序狀態(tài)的切換,這時(shí)用戶可以使用指令BL來(lái)調(diào)用子程序;另一種方法是用戶自己編寫狀態(tài)切換的程序。

          在ARMv4版本及其以前的版本中,可以使用BX指令實(shí)現(xiàn)程序狀態(tài)的切換。

          從ARMv5版本開始,下面的指令也可以用來(lái)實(shí)現(xiàn)程序的狀態(tài)切換。

          ·BX(BranchandeXchange)

          ·BLX、LDR、LDM和POP

          下面的兩個(gè)偽操作用來(lái)區(qū)分源程序中的ARM代碼和Thumb代碼。

          ·CODE16

          ·CODE32

          下面簡(jiǎn)單介紹用于狀態(tài)切換的指令和偽操作,更詳細(xì)的信息請(qǐng)分別參見相關(guān)章節(jié)。

          (1)BX指令

          ARM狀態(tài)下的BX指令,使程序跳轉(zhuǎn)到指令中指定的參數(shù)Rm指定的地址執(zhí)行程序,Rm的第0位拷貝到CPSR中T位,位[31∶1]移入PC。若Rm的bit[0]為1,則跳轉(zhuǎn)時(shí)自動(dòng)將CPSR中的標(biāo)志位T置位,即把目標(biāo)地址的代碼解釋為Thumb代碼;若Rm的位bit[0]為0,則跳轉(zhuǎn)時(shí)自動(dòng)將CPSR中的標(biāo)志位T復(fù)位,即把目標(biāo)地址代碼解釋為ARM代碼。指令的語(yǔ)法格式如下。

          BX{cond>}Rm>

          ①cond>

          為指令編碼中的條件域。它指示指令在什么條件下執(zhí)行。當(dāng)cond>忽略時(shí),指令為無(wú)條件執(zhí)行(cond=AL(Alway))。

          ②Rm>

          包含跳轉(zhuǎn)指令的目標(biāo)地址。如果Rm的bit[0]=0,目標(biāo)地址處指令為ARM指令;如果Rm的bit[0]=1,目標(biāo)地址處指令為Thumb指令。

          指令操作的偽代碼。

          指令操作的偽代碼如下面程序段所示。

          IfconditionPassed{cond}then

          TFlag=Rm[0]

          PC=RmAND0xfffffffe

          Thumb狀態(tài)下的BX指令,用于ARM和Thumb代碼間的相互調(diào)用。

          指令的語(yǔ)法格式。

          BXRm>

          其中Rm>為目標(biāo)地址寄存器,包含程序的跳轉(zhuǎn)地址。BX指令的目標(biāo)地址寄存器可以是r0~r15中的任意寄存器。

          注意

          如果Rm[1:0]=0b10,不滿足ARM指令的內(nèi)存對(duì)齊方式。指令的執(zhí)行結(jié)果不可預(yù)知。如果該指令使用r15作為目標(biāo)寄存器,其操作方式和使用其他寄存器相同。

          c++相關(guān)文章:c++教程




          評(píng)論


          相關(guā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); })();