當(dāng)前位置:首頁(yè) > 嵌入式 > 嵌入式教程
[導(dǎo)讀]Thumb以其較高的代碼密度和在窄存儲(chǔ)器上的性能,使得它在很多系統(tǒng)中得到廣泛應(yīng)用。但在很多情況下,還是不得不使用ARM指令,這是因?yàn)椋?

11.10ARM和Thumb的混合編程11.10.1互交工作基礎(chǔ)

Thumb以其較高的代碼密度和在窄存儲(chǔ)器上的性能,使得它在很多系統(tǒng)中得到廣泛應(yīng)用。但在很多情況下,還是不得不使用ARM指令,這是因?yàn)椋?/p>

①ARM代碼比Thumb代碼有更快的執(zhí)行速度;

②ARM處理器的一些特定功能必須由ARM指令實(shí)現(xiàn),其中包括PSR指令、協(xié)處理器指令;

③異常發(fā)生時(shí),處理器自動(dòng)進(jìn)入ARM狀態(tài),如果異常處理程序需要使用Thumb指令也必須通用一個(gè)ARM程序頭(ARMassemblerheader)。

基于以上原因,即使程序需要由Thumb代碼實(shí)現(xiàn),也必須通過(guò)ARM-Thumb互交(ARM-Thumbinterworking)進(jìn)入Thumb狀態(tài)。

ARM-Thumb互交是指對(duì)匯編語(yǔ)言和C/C++語(yǔ)言的ARM和Thumb代碼進(jìn)行連接的方法,它進(jìn)行兩種狀態(tài)(ARM和Thumb狀態(tài))間的切換。在進(jìn)行這種切換時(shí),有時(shí)需使用額外的代碼,這些代碼被稱(chēng)為Veneer。AAPCS定義了ARM和Thumb過(guò)程調(diào)用的標(biāo)準(zhǔn)。

從一個(gè)ARM例程調(diào)用一個(gè)Thumb例程,內(nèi)核必須進(jìn)行狀態(tài)切換。狀態(tài)的變化由CPSR的T位來(lái)顯示。在跳轉(zhuǎn)到一個(gè)例程時(shí)BX指令可用于ARM和Thumb狀態(tài)切換,具體用法如下。

在Thumb狀態(tài)調(diào)用ARM例程時(shí),采用:

BXRn;

在ARM狀態(tài)調(diào)用Thumb例程時(shí),采用:

BX{cond}Rn;

其中,Rn可以是r0~r15中的任意寄存器。

這種帶狀態(tài)切換的跳轉(zhuǎn)指令BX,將寄存器Rn的內(nèi)容拷貝到程序計(jì)數(shù)器寄存器PC,因此可以實(shí)現(xiàn)4G空間的跳轉(zhuǎn)。指令根據(jù)寄存器Rn的bit[0]來(lái)決定處理器是否進(jìn)行狀態(tài)切換,詳細(xì)內(nèi)容參見(jiàn)ARM指令一節(jié)。

下面是一段ARM程序,該程序調(diào)用虛擬的SWI_writeC子程序從存儲(chǔ)器的固定地址取出字符串“helloworld”并輸出。

AREAHello,CODE,READONLY

SWI_WriteCEQU&0 ;軟中斷調(diào)用參數(shù)

SWI_ExitEQU&11 ;程序退出軟中斷調(diào)用參數(shù)

ENTRY

STARTADRr1,TEXT ;取字符串地址

LOOPLDRBr0,[r1],#1 ;取下一字節(jié)內(nèi)容

CMPr0,#0 ;判斷是否為字符串尾

SWINESWI_WriteC ;軟中斷調(diào)用打印字符

BENLOOP ;循環(huán)

SWISWI_Exit ;軟中斷調(diào)用退出程序執(zhí)行

TEXT=“HelloWorld”,&0a,&0d,0

END

下面的代碼將上面的ARM代碼轉(zhuǎn)換成等價(jià)的Thumb代碼。

AREAHelloW_Thumb,CODE,READONLY

SWI_WriteCEQU&0 ;軟中斷調(diào)用參數(shù)

SWI_ExitEQU&11 ;程序退出軟中斷調(diào)用參數(shù)

ENTRY ;程序入口點(diǎn)

CODE32進(jìn)入ARM狀態(tài)

ADRr0,START+1 ;取得Thumb代碼入口地址

BXr0 ;進(jìn)入Thumb代碼

CODE16 ;Thumb代碼入口點(diǎn)

STARTADRr1,TEXT ;r1->"HelloWorld"

LOOPLDRBr0,[r1] ;取下一字節(jié)內(nèi)容

ADDr1,r1,#1 ;地址指針加1**T

CMPr0,#0 ;判斷是否為字符串尾

BEQDONE ;完成?**T

SWISWI_WriteC ;如果不是字符串尾

BLOOP ;繼續(xù)循環(huán)

DONESWISWI_Exit ;程序退出

ALIGN ;字對(duì)齊

TEXTDATA

"HelloWorld",&0a,&0d,&00

END

上例中,ARM代碼到Thumb代碼轉(zhuǎn)換過(guò)程中新增加的指令用“**T”標(biāo)注。

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

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

①匯編器需要知道什么時(shí)候產(chǎn)生ARM代碼、什么時(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互交子程序

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

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

②在匯編語(yǔ)言子程序中,用戶(hù)必須自己編寫(xiě)相應(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)切換的子程序名。

在這種情況下,用戶(hù)必須使用--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)切換的Veneer代碼。

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

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

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

從ARMv5版本開(kāi)始,下面的指令也可以用來(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)分別參見(jiàn)相關(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)地址的代碼解釋為T(mén)humb代碼;若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)地址處指令為T(mén)humb指令。

指令操作的偽代碼。

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

IfconditionPassed{cond}then

TFlag=Rm[0]

PC=RmAND0xfffffffe

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

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

BX<Rm>

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

注意

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

指令操作的偽代碼如下所示。

TFlag=Rm[0]

PC=Rm[31:1]<<1

ARM指令集中的BX指令和Thumb指令集中的BX指令相差較大,它們分別為不同方向的跳轉(zhuǎn)。當(dāng)r15作為目的寄存器使用時(shí),要特別注意該指令在兩個(gè)指令集中的區(qū)別。

(2)BLX指令

ARM狀態(tài)下的BLX指令使用一個(gè)寄存器中的絕對(duì)地址或標(biāo)號(hào),用于使程序跳轉(zhuǎn)到Thumb狀態(tài)或從Thumb狀態(tài)返回,該指令用分支寄存器的最低位來(lái)更新CPSR中的T位,并將返回地址寫(xiě)入到連接寄存器LR中。

指令的語(yǔ)法格式如下所示:

①BLX<target_addr>

②BLX{<cond>}<Rm>

第一種格式中,轉(zhuǎn)移目標(biāo)按下述方法計(jì)算。將指令中指定的24位偏移量進(jìn)行符號(hào)擴(kuò)展,左移兩位形成字偏移量,然后將其累加進(jìn)程序計(jì)數(shù)器PC中。這時(shí),程序計(jì)數(shù)器的內(nèi)容為BX指令地址加8字節(jié)。位H(bit[24])也加到結(jié)果地址的第一位(bit[1]),使目標(biāo)地址為半字地址,以執(zhí)行接下來(lái)的Thumb指令。計(jì)算偏移量的工作一般由ARM匯編器來(lái)完成。這種形式的跳轉(zhuǎn)指令只能實(shí)現(xiàn)±32MB空間的跳轉(zhuǎn)。

第二種格式中,寄存器Rm指定轉(zhuǎn)移目標(biāo),Rm的第0位拷貝到CPSR中的T位,bit[31:0]移入PC。

·如果Rm的bit[0]=1,則跳轉(zhuǎn)時(shí)自動(dòng)將CPSR中的標(biāo)志位T置位,即把目標(biāo)地址的代碼解釋為T(mén)humb代碼。

·如果Rm的bit[0]=0,則跳轉(zhuǎn)時(shí)自動(dòng)將CPSR中的標(biāo)志位T復(fù)位,即把目標(biāo)地址的代碼解釋為ARM代碼。

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

第一種格式BLX指令。

LR=addressoftheinstructionaftertheBLXinstruction

TFlag=1

PC=PC+PC=PC+(SignExtend(signed_immed_24)<<2)+(H<<1)

第二種格式BLX指令。

IfConditionPass{cond}then

LR=addressoftheinstructionafterthebranchinstruftion

TFlag=Rm[0]

PC=RmAND0xfffffffe

Thumb狀態(tài)下帶返回鏈接的跳轉(zhuǎn)指令BLX(1)提供了一種在Thumb狀態(tài)下無(wú)條件調(diào)用ARM子程序的方法,當(dāng)從子程序返回時(shí),通常使用下面的方式之一:

·BXLR

·加載PC的LDR或LDM指令。

BLX指令不可條件執(zhí)行,可以實(shí)現(xiàn)在大約±4MB的地址空間范圍內(nèi)跳轉(zhuǎn),實(shí)現(xiàn)方法是將一條BLX指令編譯成兩條16位的Thumb指令,從而實(shí)現(xiàn)上述跳轉(zhuǎn)。對(duì)編譯后的兩條指令說(shuō)明如下。

①H=10的跳轉(zhuǎn)指令。該跳轉(zhuǎn)包含跳轉(zhuǎn)偏移量的高位部分。

②H=01的跳轉(zhuǎn)指令。該跳轉(zhuǎn)包含跳轉(zhuǎn)偏移量的低位部分。

指令的語(yǔ)法格式

BL<target_address>

<target_address>

指定程序跳轉(zhuǎn)的目標(biāo)地址。指令通過(guò)下面的方法計(jì)算目標(biāo)地址。

·將H=10的BL指令的offset_11域左移12位。

·將結(jié)果符號(hào)擴(kuò)展為32位。

·將得到的值加到PC寄存器中。

·與H=11的BL指令的offset_11域相加。

因此BL指令可以實(shí)現(xiàn)在大約±4MB的地址空間范圍內(nèi)跳轉(zhuǎn)。

指令操作的偽代碼為:

ifH==10then

LR=PC+(SignExtend(offset_11)<<12)

ElseifH==11then

PC=LR+(offset_11<<11)

LR=(addressofnextinstruction)|1

ElseifH==01then

PC=(LR+(offset_11<<1))AND0xFFFFFFFC

LR=(addressofnextinstruction)|1

ElseifH==01then

PC=(LR+(offset_11<<1))AND0Xfffffffc

LR=(addressofnextinstruction)|1

TFlag=0

另外Thumb狀態(tài)下包含另一種格式的BLX指令,該BLX(2)指令用于ARM和Thumb子程序間的相互調(diào)用。程序狀態(tài)字的T標(biāo)志位根據(jù)目的寄存器的bit[0]位而改變。

指令的語(yǔ)法格式為:

BLX<Rm>

其中<Rm>為目標(biāo)地址寄存器,r0~r14寄存器均可以作為目標(biāo)地址寄存器。

注意

如果在此指令中使用r15作為目的寄存器,指令的執(zhí)行結(jié)果不可預(yù)知。

此指令只在ARMv5版本以上指令集中被支持。

指令操作的偽代碼為:

LR=(addressoftheinstructionafterthisBLX)|1

TFlag=Rm[0]

PC=Rm[31:1]<<1

(3)匯編偽指令

匯編編譯器可以產(chǎn)生ARM代碼也可以產(chǎn)生Thumb代碼。使用--thumb或--16選項(xiàng)指示編譯器產(chǎn)生Thumb代碼。由于所有支持Thumb代碼的ARM處理器都從ARM狀態(tài)開(kāi)始執(zhí)行,所以必須人為地使用BX或BLX指令,使處理器狀態(tài)切換到Thumb狀態(tài)并使用下面的偽操作使編譯器產(chǎn)生Thumb代碼。

·CODE16

·CODE32

CODE32偽操作指示匯編器后面的指令為32位的ARM指令。

ARM和CODE32偽操作的意義相同。

當(dāng)匯編器對(duì)源程序進(jìn)行編譯時(shí),如果需要,將會(huì)在程序中插入空指令,以保證內(nèi)存單元字對(duì)齊。

語(yǔ)法格式如下。

ARM

CODE32

使用在同時(shí)包含ARM指令和Thumb指令的源文件中。當(dāng)需要從ARM指令序列切換到Thumb指令序列時(shí),使用偽操作ARM(或CODE32);當(dāng)需要從Thumb指令序列切換到ARM指令序列時(shí)使用Thumb偽操作。ARM(或CODE32)偽操作只是指示匯編器后面的指令類(lèi)型是ARM指令。該偽操作本身并不進(jìn)行程序狀態(tài)的切換,要進(jìn)行狀態(tài)切換,可以使用BX指令操作。

CODE16偽指令通知編譯器,其后的指令序列為16位的Thumb指令。

語(yǔ)法格式如下。

CODE16

若在匯編源程序中同時(shí)包含ARM指令和Thumb指令時(shí),可用CODE16偽指令通知編譯器其后的指令序列為16位的Thumb指令。

(4)編程實(shí)例

PRESERVE8

AREAAddReg,CODE,READONLY ;段名為AddReg,屬性為READONLY

ENTRY ;程序入口

;SECTION1

main

ADRr0,ThumbProg+1 ;確定跳轉(zhuǎn)地址

;并將bit[0]置1

;使程序切換到thumb狀態(tài)

BXr0 ;程序跳轉(zhuǎn)并執(zhí)行狀態(tài)切換

;SECTION2

CODE16 ;Thumb代碼指示偽操作

ThumbProg

MOVr2,#2 ;r2=2

MOVr3,#3 ;r2=3

ADDr2,r2,r3 ;r2=r2+r3

ADRr0,ARMProg

BXr0 ;程序跳轉(zhuǎn)并執(zhí)行狀態(tài)切換

;SECTION3

CODE32 ;ARM代碼指示偽操作

ARMProg

MOVr4,#4

MOVr5,#5

ADDr4,r4,r5

;SECTION4

stopMOVr0,#0x18 ;設(shè)置semihosting軟中斷號(hào)

LDRr1,=0x20026 ;ADP_Stopped_ApplicationExit

SWI0x123456 ;ARMsemihostingSWI軟中斷調(diào)用

END ;文件結(jié)束

上面的例子分為4部分,通過(guò)下面的步驟編譯和運(yùn)行。

①使用文本編輯器,如notepad,輸入上面的代碼,并保存成文件addreg.s;

②在命令行中鍵入?yún)R編命令armasm–gaddreg.s;

③在命令行中鍵入鏈接命令armlinkaddreg.o-oaddreg;

④使用調(diào)試器(Debugger)(如,RealViewDebuggerorAXD)運(yùn)行映像文件。可以使用單步執(zhí)行,觀察代碼在Thumb狀態(tài)下的執(zhí)行。

注意

Thumb代碼的地址標(biāo)號(hào)如果用偽操作export聲明為“外部的”,則連接器會(huì)自動(dòng)調(diào)整該地址標(biāo)號(hào)使其bit[0]等于1;如果該地址標(biāo)號(hào)沒(méi)有被聲明為“外部的”,則使用者必須手動(dòng)地對(duì)標(biāo)號(hào)進(jìn)行調(diào)整,如上例中的ThumProg+1。

(5)ARMv5架構(gòu)下的狀態(tài)切換

在ARMv5體系結(jié)構(gòu)的指令集中,增加了下面兩條指令用于ARM和Thumb代碼互交。

·BLXaddress

該指令跳轉(zhuǎn)到指令中指定的地址處執(zhí)行程序并進(jìn)行程序狀態(tài)切換,該地址是“PC相關(guān)的”,地址范圍為±32MB(ARM狀態(tài))或±4MB(Thumb狀態(tài))。

·BLXregister

在該中格式的跳轉(zhuǎn)指令中寄存器Rm指定轉(zhuǎn)移目標(biāo),Rm的第0位拷貝到CPSR中的T位,bit[31:0]移入PC。

使用上面兩條指令,在執(zhí)行程序跳轉(zhuǎn)之前,處理器自動(dòng)將返回連接寄存器LR的bit[0]位更新為CPSR寄存器的T位,所以無(wú)論處理器狀態(tài)是否發(fā)生變化,程序都能正確返回。

當(dāng)使用LDR、LDM及POP指令向PC寄存器中賦值時(shí),寄存器CPSR中的Thumb位將被設(shè)置成PC寄存器的bit[0],這時(shí)就實(shí)現(xiàn)了程序狀態(tài)的切換。這種方法在子程序的返回時(shí)非常有效,同樣的指令可以根據(jù)需要返回到ARM狀態(tài)或Thumb狀態(tài)。

連接器在對(duì)目標(biāo)代碼進(jìn)行連續(xù)時(shí),將代碼中的地址標(biāo)號(hào)分為3類(lèi)。

·ARM指令地址標(biāo)號(hào)。

·Thumb指令地址標(biāo)號(hào)。

·數(shù)據(jù)(Data)地址標(biāo)號(hào)。

當(dāng)連接器重定位Thumb代碼中的地址標(biāo)號(hào)時(shí),地址標(biāo)號(hào)的bit[0]位將被自動(dòng)設(shè)置為1。這就意味著跳轉(zhuǎn)指令(這些指令包括BX、BLX和LDR)可以根據(jù)目標(biāo)地址正確的進(jìn)行狀態(tài)切換。

注意

上面提到的連接器自動(dòng)設(shè)置目的地址的行為,只有在ARMv5及其以上版本中支持。

2.使用C和C++語(yǔ)言實(shí)現(xiàn)互交

對(duì)于不同的C和C++源程序,可以有些程序中包含ARM指令,有些程序中包含Thumb指令,這些程序可以相互調(diào)用,只是在編譯這些程序時(shí)指定--apcs/interwork選項(xiàng)。當(dāng)使用了--apcs/interwork選項(xiàng),編譯器會(huì)自動(dòng)進(jìn)行一些相應(yīng)處理;連接器在檢測(cè)到程序中存在互交工作時(shí),會(huì)生成一些用于程序狀態(tài)切換的代碼。

(1)代碼編譯

可以使用下面的指令,將C或C++程序編譯為可以執(zhí)行互交的目標(biāo)代碼。

armcc--c90--thumb--apcs/interwork

armcc--c90--arm--apcs/interwork

armcc--cpp--thumb--apcs/interwork

armcc--cpp--arm--apcs/interwork

注意

--cpp是C++文件(文件后綴為.cpp)默認(rèn)的編譯選項(xiàng)。

使用--apcs/interwork選項(xiàng)對(duì)文件進(jìn)行編譯時(shí),編譯器會(huì)進(jìn)行如下處理。

·對(duì)于葉子程序(leaffunction,即程序中沒(méi)有其他子程序調(diào)用的程序),編譯器將程序中的“MOVPC,LR”指令替換成“BXLR”指令,因?yàn)?ldquo;MOVPC”指令不能進(jìn)行狀態(tài)切換。

·對(duì)于非葉子程序,要進(jìn)行一系列的指令替換,如:

POP{r4,r5,pc}

替換為:

POP{r4,r5}

POP{r3}

BXr3

下面的例子顯示了一段帶子程序調(diào)用的C語(yǔ)言程序,使用--apcs/interwork選項(xiàng)進(jìn)行編譯時(shí),對(duì)代碼產(chǎn)生的影響。

C語(yǔ)言源程序。

Voidfunc(void)

{

….

Sub()

..

}

使用armcc--apcs/interwork選項(xiàng)進(jìn)行編譯產(chǎn)生結(jié)果如下。

Func

STMFDsp!,{r4-r7,lr}

….

BLsub

….

LDMFDsp!,{r4-r7,lr}

BXlr

使用tcc--apcs/interwork選項(xiàng)進(jìn)行編譯產(chǎn)生結(jié)果如下。

PUSH{r4-r7,lr}

….

BLsub

….

POP{r4-r7}

POP{r3}

BX

(2)C語(yǔ)言的互交實(shí)例

下面的例子顯示了一個(gè)Thumb狀態(tài)下的代碼通過(guò)互交調(diào)用ARM子程序;而后又在ARM子程序中調(diào)用Thumb指令集的庫(kù)函數(shù)printf()。

/*********************

*thumbmain.c*

**********************/

#include<stdio.h>

externvoidarm_function(void);

intmain(void)

{

printf("HellofromThumbWorld\n");

arm_function();

printf("AndgoodbyefromThumbWorld\n");

return(0);

}

/*********************

*armsub.c*

**********************/

#include<stdio.h>

voidarm_function(void)

{

printf("HelloandGoodbyefromARMworld\n");

}

使用下面的命令對(duì)程序進(jìn)行編譯連接。

①編譯生成帶互交的Thumb代碼。

armcc--thumb-c-g--apcs/interwork-othumbmain.othumbmain.c

②編譯生成帶互交的ARM代碼。

armcc-c-g--apcs/interwork-oarmsub.oarmsub.c

③連接目標(biāo)文件。

armlinkthumbmain.oarmsub.o-othumbtoarm.axf

另外,可以使用--info選項(xiàng)使連接器輸出由于互交所增加的代碼大小。

armlinkarmsub.othumbmain.o-othumbtoarm.axf--infoveneers

輸出信息如下所示。

AddingVeneerstotheimage

AddingTAveneer(4bytes,Inline)forcallto'arm_function'fromthumbmain.o(.text).

AddingATveneer(8bytes,Inline)forcallto'__0printf'fromarmsub.o(.text).

AddingATveneer(8bytes,Inline)forcallto'__rt_lib_init'fromkernel.o(.text).

AddingATveneer(12bytes,Long)forcallto'__rt_lib_shutdown'fromkernel.o(.text).

AddingTAveneer(4bytes,Inline)forcallto'__rt_memclr_w'fromstdio.o(.text).

AddingTAveneer(4bytes,Inline)forcallto'__rt_raise'fromstdio.o(.text).

AddingTAveneer(8bytes,Short)forcallto'__rt_exit'fromexit.o(.text).

AddingTAveneer(4bytes,Inline)forcallto'__user_libspace'fromfree.o(.text).

AddingTAveneer(4bytes,Inline)forcallto'_fp_init'fromlib_init.o(.text).

AddingTAveneer(4bytes,Inline)forcallto'__heap_extend'frommalloc.o(.text).

AddingATveneer(8bytes,Inline)forcallto'__raise'fromrt_raise.o(.text).

AddingTAveneer(4bytes,Inline)forcallto'__rt_errno_addr'fromftell.o(.text).

12Veneer(s)(total72bytes)addedtotheimage.

(3)Thumb狀態(tài)下的功能指針

任何指向Thumb函數(shù)(由Thumb指令完成的功能函數(shù)并且其返回狀態(tài)也為T(mén)humb狀態(tài))的指針,其最低有效位(LSB)必為1。

當(dāng)重定位Thumb代碼中的地址標(biāo)號(hào)時(shí),連接器將自動(dòng)設(shè)置地址的最低有效位。如果在程序中使用絕對(duì)地址,連接器將無(wú)法完成該設(shè)置。因此,如果在Thumb代碼中使用絕對(duì)地址時(shí),必須手工設(shè)置為其地址加1。

下面的例子顯示了Thumb代碼的功能指針的使用。

typedefint(*FN)();

myfunc(){

FNfnptrs[]={

(FN)(0x8084+1), //有效的Thumb地址

(FN)(0x8074) //無(wú)效的Thumb地址

};

FN*myfunctions=fnptrs;

myfunctions[0](); //調(diào)用成功

myfunctions[1](); //調(diào)用失敗

}

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專(zhuān)欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車(chē)的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國(guó)汽車(chē)技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車(chē)工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車(chē)。 SODA V工具的開(kāi)發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車(chē) 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來(lái)越多用戶(hù)希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來(lái)越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場(chǎng)的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開(kāi)幕式在貴陽(yáng)舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱(chēng),數(shù)字世界的話(huà)語(yǔ)權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營(yíng)業(yè)績(jī)穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤(rùn)率延續(xù)升勢(shì) 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長(zhǎng) 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競(jìng)爭(zhēng)力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競(jìng)爭(zhēng)優(yōu)勢(shì)...

關(guān)鍵字: 通信 BSP 電信運(yùn)營(yíng)商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國(guó)電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場(chǎng) NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長(zhǎng)三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡(jiǎn)稱(chēng)"軟通動(dòng)力")與長(zhǎng)三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉