《ARM嵌入式系統(tǒng)基礎(chǔ)及應(yīng)用》課件第4章_第1頁
《ARM嵌入式系統(tǒng)基礎(chǔ)及應(yīng)用》課件第4章_第2頁
《ARM嵌入式系統(tǒng)基礎(chǔ)及應(yīng)用》課件第4章_第3頁
《ARM嵌入式系統(tǒng)基礎(chǔ)及應(yīng)用》課件第4章_第4頁
《ARM嵌入式系統(tǒng)基礎(chǔ)及應(yīng)用》課件第4章_第5頁
已閱讀5頁,還剩231頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第4章ARM編程與調(diào)試4.1ARM指令系統(tǒng)4.2ARM匯編語言設(shè)計(jì)4.3ARMC語言設(shè)計(jì)4.4ADS開發(fā)平臺(tái)4.5SDT開發(fā)平臺(tái)4.6基于JTAG的調(diào)試系統(tǒng)4.7仿真器調(diào)試系統(tǒng)4.8本章小結(jié)

ARM微處理器是基于精簡(jiǎn)指令集計(jì)算機(jī)(RISC)原理設(shè)計(jì)的。ARM體系提供兩種指令集:32位的ARM指令集和16位的Thumb指令集。ARM指令集執(zhí)行效率高,但是代碼密度低。4.1ARM指令系統(tǒng)Thumb指令集是ARM指令集的功能子集,它具有較高的代碼密度,同時(shí)保持了ARM大多數(shù)性能上的優(yōu)勢(shì)。ARM程序和Thumb程序可以相互調(diào)用,且兩種狀態(tài)之間的切換開銷幾乎為零。4.1.1ARM指令介紹

ARM指令包括數(shù)據(jù)處理指令、數(shù)據(jù)傳送指令、控制流指令、分支、陷入系統(tǒng)代碼。

ARM指令字長(zhǎng)為固定的32位,基本格式如下:

<opcode>{<cond>}{S}<Rd>,<Rn>,{<operand2>}

其中<>號(hào)內(nèi)的項(xiàng)是必需的,{}號(hào)內(nèi)的項(xiàng)是可選的。各項(xiàng)的含義如下:

opcode:指令助記符,如AND表示邏輯與指令;

cond:指令執(zhí)行條件;

S:指令的操作是否影響CPRS寄存器的值;

Rd:目標(biāo)寄存器;

Rn:包含第一個(gè)操作數(shù)的寄存器;

operand2:第二個(gè)操作數(shù)。

指令中的第二個(gè)操作數(shù)“operand2”有很多表示方法,靈活地使用這些表示方法能夠提高代碼效率。它包括以下形式。表4.1ARM指令編碼格式

1.常數(shù)表達(dá)式

常數(shù)表達(dá)式

#immed_8r必須對(duì)應(yīng)8位位圖,即是由一個(gè)8位的常數(shù)通過循環(huán)右移偶數(shù)位得到。所以不是每一個(gè)32位的常數(shù)都是合法的,只有通過以上的移位方法得到的常數(shù)才是合法的。

合法的常量如下:

0xff,0x3fc,0xff00,0x104,200。

不合法的常量如下:

0x102,0x1010,511,0xff1,0xffff。常量表達(dá)式應(yīng)用示例如下:

MOVR0,#0X104 ;令R0的數(shù)值為0X104

ANDR1,R2,#0xff ;R2和0xff與,并把結(jié)果保存在R1中

2.寄存器方式

在寄存器方式Rm下,指令的操作數(shù)“operand2”為寄存器的數(shù)值。

寄存器方式應(yīng)用示例如下:

MOVR1,R3 ;將R3的數(shù)值放到R1中

SUBR1,R2,R3 ;R1的數(shù)值等于R2的數(shù)值減去R3的數(shù)值

3.寄存器移位方式

在寄存器移位方式下,指令的操作數(shù)“operand2”為寄存器移位后所得的結(jié)果。

移位方式如下:

LSL#m ;邏輯左移m位(1≤m≤31)

LSR#m ;邏輯右移m位(1≤m≤31)

ASL#m ;算術(shù)左移m位(1≤m≤32)

ASR#m ;算術(shù)右移m位(1≤m≤32)

ROR#m ;循環(huán)右移m位(1≤m≤31)

RRX ;右移一位,并用CPSR中的C條件標(biāo)志位填補(bǔ)空出的位寄存器移位方式應(yīng)用示例如下:

ADDR1,R1,R1,LSL#4 ;R1=R1+R1*24=R1*17

SUBR1,R1,R2,LSRR3 ;R1=R1-R2/2R3

ARM指令中的第28~32位是給cond用的,它可以組成16種條件碼。當(dāng)ARM微處理器工作在ARM狀態(tài)時(shí),所有的指令都是根據(jù)CPSR中的條件標(biāo)志位狀態(tài)與指令的條件碼是否符合來決定是否執(zhí)行。當(dāng)執(zhí)行的條件滿足時(shí)就執(zhí)行該命令,否則指令被忽略,轉(zhuǎn)向下一條指令。例如,在跳轉(zhuǎn)指令B后面加上后綴EQ(即BEQ),則表示“相等則跳轉(zhuǎn)”,即當(dāng)CPSR中的Z標(biāo)志置位時(shí)發(fā)生跳轉(zhuǎn)。16種條件碼的含義及助記符如表4.2所示,其中只有15種可以使用,第16種(1111)為系統(tǒng)保留。

表4.216種條件碼的含義及助記符續(xù)表4.1.2ARM指令尋址方式

尋址方式是根據(jù)指令中給出的地址碼字段來實(shí)現(xiàn)尋找真實(shí)操作數(shù)地址的方式。ARM指令的尋址方式有以下幾種。

1.立即尋址

立即尋址又叫做立即數(shù)尋址,操作碼字段后面的地址部分就是操作數(shù),即數(shù)據(jù)就包含在指令當(dāng)中,那么取出指令也就取到了操作數(shù)。

立即尋址方式示例如下:

MOVR0,#0x104 ;R0←0x104

ADDR0,R1,#200 ;R0←R1+200

2.寄存器尋址

指令中的地址碼字段指定了寄存器的編號(hào),將寄存器中的數(shù)值作為操作數(shù)。執(zhí)行指令時(shí)直接取出寄存器中的數(shù)值進(jìn)行操作,這種尋址方式的效率比較高。

寄存器尋址方式示例如下:

SUBR0,R1,R2 ;R0←R1-R2

MOVR0,R1 ;R0←R1

3.寄存器間接尋址

寄存器間接尋址指令中的地址碼字段給出的是一個(gè)通用寄存器的編號(hào),它是以該寄存器中的值作為操作數(shù)的地址,而操作數(shù)本身存放在存儲(chǔ)單元中。

寄存器間接尋址方式示例如下:

ADDR1,R2,[R3] ;將R3中的數(shù)值作為地址,取出此地址中的數(shù)值后與R2相加,

;結(jié)果保存在R1中

LDRR1,[R2] ;將R2中的數(shù)值作為地址,取出此地址中的數(shù)值并保存在R1中

4.寄存器偏移尋址

寄存器偏移尋址是ARM指令集特有的尋址方式,當(dāng)?shù)?個(gè)操作數(shù)是寄存器偏移方式時(shí),先將其進(jìn)行移位操作后再與第一個(gè)操作數(shù)結(jié)合。

寄存器偏移尋址方式示例如下:

MOVR0,R1,LSL#1 ;R1中的值左移一位,結(jié)果放入R0中,即R0=R1*2

ANDR0,R0,R1,LSRR2 ;R1中的值右移R2位,和R0作邏輯與操作后,結(jié)果放

;入R0中可采用的移位方式有以下幾種:

LSL:邏輯左移,寄存器中字的低端空出的位補(bǔ)0。

圖4.1循環(huán)移位操作圖示

LSR:邏輯右移,寄存器中字的高端空出的位補(bǔ)0。

ASR:算術(shù)右移,在移位過程中保持字的符號(hào)位不變,即如果原操作數(shù)為正數(shù),則在字的高端空出的位補(bǔ)0,否則補(bǔ)1。

ROR:循環(huán)右移,即由字的低端移出的位來填補(bǔ)字的高端空出位。

RRX:帶擴(kuò)展的循環(huán)右移,操作數(shù)右移一位,高端空出的位由原CPSR中的C條件標(biāo)志位填補(bǔ)。

各移位操作如圖4.1所示。

5.基址尋址

基址尋址是將基址寄存器的內(nèi)容與指令中所給出的地址偏移量相加,形成操作數(shù)的有效地址?;穼ぶ芬话阌糜谠L問基址附近的存儲(chǔ)單元。

基址尋址方式示例如下:

LDRR0,[R1,#0X0C] ;將R1中的數(shù)值加上#0X0C形成操作數(shù)的有效地址,取出

;此地址中的數(shù)值保存在R0中

LDRR0,[R1#-2] ;將R1中的數(shù)值減去2形成操作數(shù)的有效地址,取出此地址

;中的數(shù)值保存在R0中,然后R1的內(nèi)容自動(dòng)減2個(gè)字節(jié)

6.多寄存器尋址

多寄存器尋址可以一次傳送多個(gè)寄存器的值,在一條指令中最多允許傳送16個(gè)通用寄存器的值。

多寄存器尋址方式示例如下:

LDMIAR0!,{R1-R4,R7} ;將R0單元中的數(shù)據(jù)讀到R1、R2、R3、R4和R7中,

;R0自動(dòng)加1

STMIAR0!,{R1-R4,R7} ;將R1、R2、R3、R4和R7中的值保存在R0指向的地址

;單元,R0自動(dòng)加1

在使用多寄存器尋址方式的時(shí)候,寄存器子集的順序按由小到大的順序排列,連續(xù)的寄存器用連字符“-”連接,否則用“,”分隔。

7.堆棧尋址

堆棧是一個(gè)按照特定順序進(jìn)行存取的存儲(chǔ)區(qū),操作順序?yàn)椤跋冗M(jìn)后出”,它使用一個(gè)被稱做堆棧指針的專用寄存器指示當(dāng)前的操作位置,堆棧指針總是指向棧頂。當(dāng)堆棧指針指向最后壓入堆棧的有效數(shù)據(jù)時(shí),稱為滿堆棧;當(dāng)堆棧指針指向下一個(gè)將要放入數(shù)據(jù)的空位置時(shí),稱為空堆棧。

另外,根據(jù)堆棧的生成方式,堆棧又可以分為遞增堆棧和遞減堆棧。當(dāng)堆棧由低地址向高地址生成時(shí),稱為遞增堆棧;當(dāng)堆棧由高地址向低地址生成時(shí),稱為遞減堆棧。因此根據(jù)以上的劃分方式就有4種不同類型的組合。

滿遞增堆棧:堆棧指針指向最后壓入的數(shù)據(jù),且由低地址向高地址生成。如指令LDMFA、STMFA等。

空遞增堆棧:堆棧指針指向下一個(gè)將要放入數(shù)據(jù)的空位置,且由低地址向高地址生成。如指令LDMEA、STMEA等。

滿遞減堆棧:堆棧指針指向最后壓入的數(shù)據(jù),且由高地址向低地址生成。如指令LDMFD、STMFD等。

空遞減堆棧:堆棧指針指向下一個(gè)將要放入數(shù)據(jù)的空位置,且由高地址向低地址生成。如指令LDMED、STMED等。

堆棧尋址方式示例如下:

STMFDSP!,{R0-R5,LR} ;將R0~R5、LR入棧,滿遞減堆棧

LDMFDSP!,{R0-R5,LR} ;數(shù)據(jù)出棧,放入R0~R5、LR寄存器中,滿遞減堆棧

8.塊復(fù)制尋址

塊復(fù)制尋址也是一種多寄存器傳送指令,它用于將一塊數(shù)據(jù)從存儲(chǔ)器的某一位置復(fù)制到另一位置。

塊復(fù)制尋址方式示例如下:

STMDAR0!,{R1-R5} ;將R1~R5的數(shù)據(jù)保存到存儲(chǔ)器中,存儲(chǔ)器指針在保存第一

;個(gè)值之后增加,增長(zhǎng)方向?yàn)橄蛳略鲩L(zhǎng)

STMDBR0!,{R1-R5} ;將R1~R5的數(shù)據(jù)保存到存儲(chǔ)器中,存儲(chǔ)器指針在保存第一

;個(gè)值之前增加,增長(zhǎng)方向?yàn)橄蛳略鲩L(zhǎng)

STMIAR0!,{R1-R5} ;將R1~R5的數(shù)據(jù)保存到存儲(chǔ)器中,存儲(chǔ)器指針在保存第一

;個(gè)值之后增加,增長(zhǎng)方向?yàn)橄蛏显鲩L(zhǎng)

STMDBR0!,{R1-R5} ;將R1~R5的數(shù)據(jù)保存到存儲(chǔ)器中,存儲(chǔ)器指針在保存第一

;個(gè)值之前增加,增長(zhǎng)方向?yàn)橄蛏显鲩L(zhǎng)

9.相對(duì)尋址

相對(duì)尋址方式與基址尋址類似,它以程序寄存器PC提供的當(dāng)前值為基地址,指令中的地址碼作為偏移量,兩者相加后得到的地址作為操作數(shù)的有效地址。

相對(duì)尋址方式示例如下:

BLSUBR1 ;調(diào)用到SUBR1子程序

BEQLOOP ;條件跳轉(zhuǎn)到LOOP標(biāo)號(hào)處

LOOPMOVR1,#3

SUBR1

跳轉(zhuǎn)指令BL用的是相對(duì)尋址方式。4.1.3ARM指令集介紹

ARM指令集可以分為6大類,即跳轉(zhuǎn)指令、數(shù)據(jù)處理指令、程序狀態(tài)寄存器(PSR)處理指令、加載/存儲(chǔ)指令、協(xié)處理器指令和異常產(chǎn)生指令。為了更清晰地描述這些指令,有些大類的指令進(jìn)一步分為幾個(gè)小類指令來分別介紹。

1.跳轉(zhuǎn)指令

跳轉(zhuǎn)指令用于實(shí)現(xiàn)程序流程的跳轉(zhuǎn),在ARM程序中有兩種方法可以實(shí)現(xiàn)程序的跳轉(zhuǎn):一是使用跳轉(zhuǎn)指令;另一種是直接向PC寄存器中寫入目標(biāo)地址值。通過后一種方式可以實(shí)現(xiàn)在4GB空間中的任意跳轉(zhuǎn)。如果在跳轉(zhuǎn)之前結(jié)合使用“MOVLR,PC”等指令,可以保存返回地址值,從而實(shí)現(xiàn)了在4GB連續(xù)的線性地址空間中進(jìn)行子程序的調(diào)用。

ARM跳轉(zhuǎn)指令可以實(shí)現(xiàn)從當(dāng)前指令向前或向后32MB的地址空間內(nèi)的跳轉(zhuǎn),它包括以下4類指令:

(1)

B指令——跳轉(zhuǎn)指令。

格式:B{cond}<地址>

B指令是最簡(jiǎn)單的跳轉(zhuǎn)指令。當(dāng)遇到B指令時(shí),ARM處理器就立即跳轉(zhuǎn)到給定的地址處,從那里開始執(zhí)行。需要注意的是,指令中的地址是相對(duì)當(dāng)前PC值的一個(gè)偏移量,而不是目標(biāo)地址。目標(biāo)地址應(yīng)是先將指令中的24位帶符號(hào)的補(bǔ)碼立即數(shù)擴(kuò)展為32位(擴(kuò)展其符號(hào)位),再將此32位數(shù)左移兩位得到的值與PC寄存器的值相加所得的結(jié)果。

(2)

BL指令——帶返回的跳轉(zhuǎn)指令。

格式:BL{cond}<地址>

BL跳轉(zhuǎn)指令常用于實(shí)現(xiàn)子程序的調(diào)用。跳轉(zhuǎn)之前,在寄存器R14中保存PC的當(dāng)前內(nèi)容,返回時(shí)通過將R14的內(nèi)容重新裝載到PC中來實(shí)現(xiàn)。

(3)

BLX指令——帶返回和切換的跳轉(zhuǎn)指令。

格式:BLX<地址>

BLX{cond}Rm

第一種格式的BLX指令實(shí)現(xiàn)從ARM指令集跳轉(zhuǎn)到指令中的目標(biāo)地址,并將處理器的工作狀態(tài)由ARM狀態(tài)切換到Thumb狀態(tài),同時(shí)將PC的當(dāng)前內(nèi)容保存到寄存器R14中。

第二種格式的BLX指令的目標(biāo)地址存放在指令中的寄存器Rm中,目標(biāo)地址指令既可以是ARM指令,也可以是Thumb指令,具體是由CPSR中的T位決定的。

因此當(dāng)子程序?yàn)門humb指令集而調(diào)用者為ARM指令集時(shí),可以通過BLX指令實(shí)現(xiàn)子程序的調(diào)用和處理器工作狀態(tài)的切換。同時(shí),子程序的返回可以通過將寄存器R14中的值復(fù)制到PC中來完成。

(4)

BX指令——帶狀態(tài)切換的跳轉(zhuǎn)指令。

格式:BX{cond}Rm

BX指令跳轉(zhuǎn)到指令中所指定的目標(biāo)地址,目標(biāo)地址處的指令既可以是ARM指令,也可以是Thumb指令。

2.數(shù)據(jù)處理指令

數(shù)據(jù)處理指令大致分為3類:數(shù)據(jù)傳送指令、算術(shù)邏輯運(yùn)算指令和比較指令。數(shù)據(jù)處理指令只能對(duì)寄存器的內(nèi)容進(jìn)行操作,而不能對(duì)內(nèi)存中的數(shù)據(jù)進(jìn)行操作。所有的ARM數(shù)據(jù)處理指令都可以選擇S作為后綴,以影響狀態(tài)標(biāo)志。比較指令不需要采用后綴,它會(huì)直接影響狀態(tài)標(biāo)志位。

1)數(shù)據(jù)傳送指令

數(shù)據(jù)傳送指令用于在寄存器和存儲(chǔ)器之間進(jìn)行數(shù)據(jù)的雙向傳輸。

(1)

MOV——數(shù)據(jù)傳送指令。

格式:MOV{cond}{S}Rd,operand2

MOV指令將操作數(shù)operand2傳送到目標(biāo)寄存器Rd中,其中operand2可以是寄存器、被移位的寄存器以及立即數(shù)。該指令用于移位運(yùn)算等操作。

(2)

MVN——數(shù)據(jù)求反傳送指令。

格式:MVN{cond}{S}Rd,operand2

MVN指令將操作數(shù)operand2按位取反后傳送到目標(biāo)寄存器Rd中,operand2同上。因?yàn)槠渚哂腥》垂δ埽钥梢匝b載范圍更廣的立即數(shù)。

2)算術(shù)邏輯運(yùn)算指令

算術(shù)邏輯運(yùn)算指令用于完成常用的算術(shù)與邏輯運(yùn)算,不僅將運(yùn)算結(jié)果存入目標(biāo)寄存器中,同時(shí)更新CPSR中相應(yīng)的條件標(biāo)志位。

(1)

ADD——加法指令。

格式:ADD{cond}{S}Rd,Rn,operand2

ADD指令將操作數(shù)operand2與Rn的值相加,結(jié)果保存在Rd寄存器中,operand2同上,Rn是寄存器。ADD指令可用于無符號(hào)和有符號(hào)數(shù)的加法運(yùn)算。

(2)

SUB——減法指令。

格式:SUB{cond}{S}Rd,Rn,operand2

SUB指令將操作數(shù)Rn減去operand2,結(jié)果保存在Rd中,operand2同上,Rn是寄存器。SUB指令可用于無符號(hào)和有符號(hào)數(shù)的減法運(yùn)算。

(3)

RSB——逆向減法指令。

格式:RSB{cond}{S}Rd,Rn,operand2

RSB指令將操作數(shù)operand2減去Rn,結(jié)果保存在Rd中,operand2同上,Rn是寄存器。該指令同樣可用于無符號(hào)和有符號(hào)數(shù)的減法運(yùn)算。

(4)

ADC——帶進(jìn)位加法指令。

格式:ADC{cond}{S}Rd,Rn,operand2

ADC指令將operand2與Rn中的值相加,再加上CPSR中的C條件標(biāo)志位的值,把結(jié)果保存在Rd中。由于它使用了進(jìn)位標(biāo)志位,因此可以進(jìn)行比32位數(shù)大的加法運(yùn)算。

(5)

SBC——帶進(jìn)位減法指令。

格式:SBC{cond}{S}Rd,Rn,operand2

SBC指令將寄存器Rn中的值減去operand2,再減去CPSR中的C條件標(biāo)志位的非(即若C標(biāo)志位為0則減1,反之減0),結(jié)果保存在Rd中。由于使用了進(jìn)位標(biāo)志位來借位,因此可以進(jìn)行大于32位的減法操作。

(6)

RSC——帶進(jìn)位逆向減法指令。

格式:RSC{cond}{S}Rd,Rn,operand2

運(yùn)算方式同SBC,但是是用operand2減去Rn。

(7)

AND——邏輯與操作指令。

格式:AND{cond}{S}Rd,Rn,operand2

AND指令將兩個(gè)操作數(shù)進(jìn)行按位邏輯與操作,結(jié)果保存到Rd中。該指令常用于屏蔽Rn的某些位。

(8)

ORR——邏輯或指令。

格式:ORR{cond}{S}Rd,Rn,operand2

ORR指令將兩個(gè)操作數(shù)進(jìn)行邏輯或操作,結(jié)果保存到Rd中。該指令常用于設(shè)置Rn的某些位。

(9)

EOR——邏輯異或指令。

格式:EOR{cond}{S}Rd,Rn,operand2

EOR指令將兩個(gè)操作數(shù)進(jìn)行邏輯異或操作,結(jié)果保存到Rd中。該指令常用于對(duì)Rn的某些位取反。

(10)

BIC——位清除指令。

格式:BIC{cond}{S}Rd,Rn,operand2

BIC指令將Rn的值與operand2的反碼按位作邏輯與操作,結(jié)果保存到Rd中。operand2為32位的掩碼,如果在掩碼中設(shè)置了某一位則清除該位,未設(shè)置的掩碼位保持不變。

3)比較指令

比較指令不保存運(yùn)算結(jié)果,只更新CPSR中的標(biāo)志位。

(1)

CMP——比較指令。

格式:CMP{cond}Rn,operand2

CMP指令將Rn中的值減去operand2的值,根據(jù)運(yùn)算結(jié)果設(shè)置CPSR中的條件標(biāo)志位,以便后面的指令進(jìn)行條件執(zhí)行。它與SUBS指令的區(qū)別在于,CMP指令不保存運(yùn)算結(jié)果。

(2)

CMN——基于相反數(shù)的比較指令。

格式:CMN{cond}Rn,operand2

CMN指令將Rn中的值加上operand2的值,根據(jù)運(yùn)算結(jié)果設(shè)置CPSR中的條件標(biāo)志位,以便后面的指令進(jìn)行條件執(zhí)行。它與ADDS指令的區(qū)別在于,CMN指令不保存運(yùn)算結(jié)果。

(3)

TST——位測(cè)試指令。

格式:TST{cond}Rn,operand2

TST指令對(duì)兩個(gè)操作數(shù)進(jìn)行按位邏輯與操作,根據(jù)運(yùn)算結(jié)果設(shè)置CPSR中的條件標(biāo)志位。該指令一般用來測(cè)試是否設(shè)置了特定的位。Rn為要測(cè)試的數(shù)據(jù)字,而operand2是一個(gè)位掩碼。經(jīng)測(cè)試,如果匹配則Z置位,否則Z復(fù)位。

(4)

TEQ——相等測(cè)試指令。

格式:TEQ{cond}Rn,operand2

類似于TST指令,但TEQ指令是對(duì)兩個(gè)操作數(shù)進(jìn)行按位邏輯異或操作。與EORS指令的區(qū)別同樣在于它不保存運(yùn)算結(jié)果。在用TEQ進(jìn)行相等測(cè)試時(shí),它不會(huì)影響進(jìn)位標(biāo)志(不像CMP),TEQ指令常與EQNE條件碼配合使用,若兩個(gè)數(shù)據(jù)相等則EQ有效,反之NE有效。

另外,ARM指令集中還包括兩類乘法指令:一類是32位的乘法指令,即操作結(jié)果為32位;另一類是64位的乘法指令,即操作結(jié)果為64位。具體包括以下6條指令:

(1)

MUL——32位乘法指令。

格式:MUL{cond}{S}Rd,Rm,Rs

MUL提供了32位整數(shù)乘法,將Rm和Rs中的值相乘,結(jié)果保存在Rd中。Rm和Rs為32位的有符號(hào)數(shù)或無符號(hào)數(shù)。

(2)

MLA——32位帶加法的乘法指令。

格式:MLA{cond}{S}Rd,Rm,Rs,Rn

同MUL,但將乘積后得到的結(jié)果再加上Rn。

(3)

UMULL——64位無符號(hào)數(shù)乘法指令。

格式:UMULL{cond}{S}RdLo,RdHi,Rm,Rs

將Rm和Rs中的值作無符號(hào)數(shù)的乘法,乘積結(jié)果的低32位放在RdLo中,高32位放在RdHi中。Rm和Rs都為32位的有符號(hào)數(shù)或無符號(hào)數(shù)。

(4)

UMLAL——64位帶加法的無符號(hào)數(shù)乘法指令。

格式:UMLAL{cond}{S}RdLo,RdHi,Rm,Rs

將Rm和Rs中的值作無符號(hào)數(shù)的乘法,得到的64位乘積結(jié)果與RdLo和RdHi相加。低32位保存在RdLo中,高32位保存在RdHi中。

(5)

SMULL——64位有符號(hào)數(shù)乘法指令。

格式:SMULL{cond}{S}RdLo,RdHi,Rm,Rs

與UMULL類似,不過SMULL是作64位有符號(hào)數(shù)的相乘操作。

(6)

SMLAL——64位帶加法的有符號(hào)數(shù)乘法指令。

格式:SMLAL{cond}{S}RdLo,RdHi,Rm,Rs

與UMLAL類似,不過SMLAL是作64位有符號(hào)數(shù)的相乘操作。

3.程序狀態(tài)寄存器處理指令

程序狀態(tài)寄存器處理指令用于在狀態(tài)寄存器和通用寄存器之間傳送數(shù)據(jù),包括以下兩條指令。

(1)

MRS——讀狀態(tài)寄存器指令。

格式:MRS{cond}Rd,psr

其中psr為CPSR或SPSR,Rd為目標(biāo)寄存器,不允許為R15。MRS指令把程序狀態(tài)寄存器的內(nèi)容傳送到通用寄存器中,該指令主要用于兩種情況:一是當(dāng)需要改變狀態(tài)寄存器的值時(shí),就用MRS指令把數(shù)據(jù)從狀態(tài)寄存器送入通用寄存器,修改之后再寫回狀態(tài)寄存器。另一種情況是當(dāng)在處理異常或進(jìn)程切換,需要保存狀態(tài)寄存器的值時(shí),可用該指令把狀態(tài)寄存器的值讀出,然后進(jìn)行保存。

(2)

MSR——寫狀態(tài)寄存器指令。

格式:MSR{cond}psr_fields,#immed_8r

MSR{cond}psr_fields,Rm

psr為CPSR或SPSR。

fields:指定傳送的區(qū)域,狀態(tài)寄存器的32位可以分為4個(gè)8位的域:bit[7:0]為控制域,用c表示;bit[15:8]為擴(kuò)展域,用x表示;bit[23:16]為狀態(tài)域,用s表示;bit[31:24]為標(biāo)志域,用f表示。

#immed_8r:將要傳送到狀態(tài)寄存器的立即數(shù)。

Rm:源寄存器,存放將要傳送到狀態(tài)寄存器指定域的數(shù)據(jù)。

MSR:用于將操作數(shù)的內(nèi)容傳送到程序狀態(tài)寄存器中的指定域中。通常用于恢復(fù)或改變狀態(tài)寄存器的內(nèi)容。如:當(dāng)退出中斷異常處理時(shí),如果事先保存了狀態(tài)寄存器的內(nèi)容,則可以通過MSR指令將保存的值恢復(fù)到狀態(tài)寄存器中。其中,MRS與MSR通常配合使用實(shí)現(xiàn)CPSR或SPSR寄存器的“讀—修改—寫”操作,來進(jìn)行處理器模式切換。需要注意的是,程序不能通過直接修改CPSR中T控制位將程序狀態(tài)從ARM狀態(tài)切換到Thumb狀態(tài),而必須通過執(zhí)行BX等指令來實(shí)現(xiàn)。

4.加載/存儲(chǔ)指令

加載指令用于從內(nèi)存中讀取數(shù)據(jù)放入寄存器中;存儲(chǔ)指令用于將寄存器的值保存到內(nèi)存。加載/存儲(chǔ)指令可以分為單寄存器操作指令和多寄存器操作指令。單寄存器加載/存儲(chǔ)指令可分為字和無符號(hào)字節(jié)加載/存儲(chǔ)指令與半字和有符號(hào)字節(jié)加載/存儲(chǔ)指令。前者包括以下4種指令:

(1)

LDR(T)——字?jǐn)?shù)據(jù)讀取指令(用戶模式的字?jǐn)?shù)據(jù)讀取指令)。

格式:LDR(T){cond}Rd,<地址>

LDR指令通常用于兩種情況:一種情況是從指定地址讀取32位的字到目標(biāo)寄存器Rd中;另一種情況是當(dāng)PC作為指令中的目標(biāo)寄存器時(shí),指令能實(shí)現(xiàn)程序跳轉(zhuǎn)的功能。T為可選后綴,如果指令有T,就為用戶模式下的字?jǐn)?shù)據(jù)讀取指令,也就是即使處理器是在特權(quán)模式下,存儲(chǔ)系統(tǒng)也將訪問看成是在處理器的用戶模式下進(jìn)行的。

(2)

LDRB(T)——字節(jié)數(shù)據(jù)讀取指令(用戶模式的字節(jié)數(shù)據(jù)讀取指令)。

格式:LDRB(T){cond}Rd,<地址>

LDRB指令用于從指定地址中讀取8位的字節(jié)數(shù)據(jù)到目標(biāo)寄存器Rd中,并將寄存器的高24位清零。同樣,T也是可選后綴,有T就為用戶模式下的字節(jié)數(shù)據(jù)讀取指令。

(3)

STR(T)——字?jǐn)?shù)據(jù)寫入指令(用戶模式字?jǐn)?shù)據(jù)寫入指令)。

格式:STR(T){cond}Rd,<地址>

STR指令把存儲(chǔ)在寄存器Rd中的字?jǐn)?shù)據(jù)寫入到指令中指定地址的存儲(chǔ)單元中。同樣,T也是可選后綴,作用同前。

(4)

STRB(T)——字節(jié)數(shù)據(jù)寫入指令(用戶模式字節(jié)數(shù)據(jù)寫入指令)。

格式:STRB(T){cond}Rd,<地址>

STRB指令用于把寄存器Rd中低8位的字節(jié)數(shù)據(jù)寫入到指定地址的存儲(chǔ)單元。T的作用同前。半字和有符號(hào)字節(jié)加載/存儲(chǔ)指令包括以下4種:

(1)

LDRH——半字?jǐn)?shù)據(jù)讀取指令。

格式:LDRH{cond}Rd,<地址>

LDRH指令用于從指定地址中讀取16位的半字?jǐn)?shù)據(jù)到目標(biāo)寄存器Rd中,并將寄存器的高16位清零。

(2)

LDRSB——有符號(hào)的字節(jié)數(shù)據(jù)讀取指令。

格式:LDRSB{cond}Rd,<地址>

LDRSB指令用于從指定地址中讀取8位的字節(jié)數(shù)據(jù)到目標(biāo)寄存器Rd中,并將寄存器的高24位設(shè)置為該字節(jié)數(shù)據(jù)的符號(hào)位的值(即將該8位字節(jié)數(shù)據(jù)進(jìn)行符號(hào)位擴(kuò)展,生成32位字?jǐn)?shù)據(jù))。

(3)

LDRSH——有符號(hào)的半字?jǐn)?shù)據(jù)讀取指令。

格式:LDRSH{cond}Rd,<地址>

LDRSH指令用于從指定地址中讀取16位的半字節(jié)數(shù)據(jù)到目標(biāo)寄存器Rd中,并將寄存器的高16位設(shè)置為該字節(jié)數(shù)據(jù)的符號(hào)位的值。

(4)

STRH——半字?jǐn)?shù)據(jù)寫入指令。

格式:STRH{cond}Rd,<地址>

STRH指令用于將寄存器Rd中的低16位的半字?jǐn)?shù)據(jù)寫入指令中指定地址的存儲(chǔ)單元。

多寄存器加載/存儲(chǔ)指令又稱為批量加載/存儲(chǔ)指令,它實(shí)現(xiàn)在一組寄存器和一塊連續(xù)的內(nèi)存單元傳輸數(shù)據(jù),主要用于現(xiàn)場(chǎng)保護(hù)﹑數(shù)據(jù)復(fù)制﹑參數(shù)傳送等。指令形式為L(zhǎng)DM/STM,LDM為加載多個(gè)寄存器,STM為存儲(chǔ)多個(gè)寄存器。允許一條指令傳送16個(gè)寄存器的任何子集或全部寄存器。

LDM/STM指令的格式如下:

LDM{cond}<模式>Rn{!},registers{^}

STM{cond}<模式>Rn{!},registers{^}

模式:控制地址的增長(zhǎng)方式,一共包括8種模式,如下所示(前4種用于數(shù)據(jù)塊的傳輸,后4種用于堆棧操作):

IA每次傳送后地址加4

IB每次傳送前地址加4

DA每次傳送后地址減4

DB每次傳送前地址減4

FD滿遞增堆棧

ED空遞增堆棧

FA滿遞減堆棧

EA空遞減堆棧

“!”:表示在操作結(jié)束后,將最后的地址寫回Rn中。

registers:寄存器,可以包含多個(gè)寄存器,使用“,”分開,且由小到大排列,如{R1,R2,R4-R7}。

“^”:若使用該后綴,則在進(jìn)行數(shù)據(jù)傳送且寄存器不包括PC時(shí),加載/存儲(chǔ)的寄存器是在用戶模式下的,而不是在當(dāng)前模式下。若在LDM指令的寄存器中包含PC的情況下使用,那么除了正常的多寄存器傳送外,

還將SPSR復(fù)制到CPSR中,這樣可用于異常處理返回。需要注意的是該后綴不允許在用戶模式和系統(tǒng)模式下使用。

在進(jìn)行數(shù)據(jù)復(fù)制時(shí),先設(shè)置好源數(shù)據(jù)指針和目標(biāo)指針,然后使用塊復(fù)制指令LDMIA/STMIA、LDMIB/STMIB、LDMDA/STMDA、LDMDB/STMDB進(jìn)行讀取和存儲(chǔ)。

在進(jìn)行堆棧操作時(shí),先設(shè)置好堆棧指針(SP),然后使用堆棧尋址指令STMFD/LDMFD、STMED/LDMED、STMFA/LDMFA、STMEA/LDMEA實(shí)現(xiàn)堆棧操作。另外,加載/存儲(chǔ)指令還包括數(shù)據(jù)交換指令SWP,格式如下:

SWP{cond}{B}Rd,Rm,[Rn]

其中B為可選后綴,若有B則交換字節(jié),否則交換32位字。SWP指令用于將一個(gè)內(nèi)存字單元(該單元的地址存放在寄存器Rn中)的內(nèi)容讀取到寄存器Rd中,并將寄存器Rm中的內(nèi)容寫入到該內(nèi)存字單元。若Rd和Rm相同,則指令表示交換該寄存器和內(nèi)存單元的內(nèi)容。如指令“SWPR1,R2,[R3]”表示將R3指向的存儲(chǔ)單元內(nèi)容讀取到R1中,并將R2中的內(nèi)容寫入R3指向的存儲(chǔ)單元。

SWPB指令只從內(nèi)存單元取出一個(gè)字節(jié)到Rd中,將Rd的高24位設(shè)置為0,同時(shí)將Rm中的低8位數(shù)值寫入到該內(nèi)存單元。

5.協(xié)處理器指令

ARM微處理器支持16個(gè)協(xié)處理器,用于各種協(xié)處理操作。在程序的執(zhí)行過程中,每個(gè)協(xié)處理器只執(zhí)行針對(duì)自身的協(xié)處理指令,而忽略其他處理器的指令。當(dāng)一個(gè)協(xié)處理器不能執(zhí)行屬于自身的協(xié)處理指令時(shí),會(huì)產(chǎn)生未定義指令異常中斷。

協(xié)處理器指令主要用于:ARM處理器初始化、ARM協(xié)處理器的數(shù)據(jù)處理操作;ARM處理器的寄存器和ARM協(xié)處理器的寄存器之間的數(shù)據(jù)傳送;ARM協(xié)處理器的寄存器和存儲(chǔ)器之間的數(shù)據(jù)傳送。ARM協(xié)處理指令包括以下5條指令:

(1)

CDP——協(xié)處理器數(shù)據(jù)操作指令。

格式:CDP{cond}coproc,opcode1,CRd,CRn,CRm,{opcode2}

cond:條件指令執(zhí)行條件碼,當(dāng)cond忽略或?yàn)?b1111時(shí),指令無條件執(zhí)行。

coproc:協(xié)處理器編碼,標(biāo)準(zhǔn)名為pn,n的范圍為0~15。

opcode1:協(xié)處理器的操作碼。

CRd:作為目標(biāo)寄存器的協(xié)處理器寄存器。

CRn:存放第一個(gè)操作數(shù)的協(xié)處理器寄存器。

CRm:存放第二個(gè)操作數(shù)的協(xié)處理器寄存器。

opcode2:可選的協(xié)處理器的操作碼。

如指令:

CDPp2,4,C3,C4,C1,7;完成對(duì)協(xié)處理器p2的初始化其中操作碼1為4,操作碼2為7,目標(biāo)寄存器為C3,原操作數(shù)寄存器為C4、C1。該類指令操作是由協(xié)處理器完成的,不涉及ARM存儲(chǔ)器和內(nèi)存單元。

(2)

LDC——協(xié)處理器數(shù)據(jù)讀取指令。

格式:LDC{cond}{L}coproc,CRd,<地址>

其中L為可選后綴,指明是長(zhǎng)整數(shù)傳送,如雙精度數(shù)據(jù)的傳送。

LDC指令用于將指令中地址所指向的存儲(chǔ)器中的字?jǐn)?shù)據(jù)讀取到協(xié)處理器寄存器中。

如指令:

LDCp2,C3,[R4#5];將內(nèi)存單元(R4+5)所對(duì)應(yīng)的數(shù)值傳送到協(xié)處理器p2的C3寄存器中

(3)

STC——協(xié)處理器數(shù)據(jù)寫入指令。

格式:STC{cond}{L}coproc,CRd,<地址>

STC指令用于將協(xié)處理器寄存器中的數(shù)據(jù)寫入到指令中指定地址所指向的存儲(chǔ)器中。

如指令:

STCp2,C3,[R4#5];將協(xié)處理器p2的C3寄存器中的內(nèi)容傳送到內(nèi)存單元(R4+5)

(4)

MCR——ARM寄存器到協(xié)處理寄存器的數(shù)據(jù)傳輸指令。

格式:MCR{cond}coproc,opcode1,CRd,CRn,CRm,{opcode2}

MCR指令用于將ARM處理寄存器中的數(shù)據(jù)傳送到協(xié)處理器寄存器中。

(5)

MRC——協(xié)處理寄存器到ARM寄存器的數(shù)據(jù)傳輸指令。

格式:MRC{cond}coproc,opcode1,CRd,CRn,CRm,{opcode2}

MRC指令用于將協(xié)處理器寄存器中的數(shù)據(jù)傳送到ARM處理寄存器中。

6.異常產(chǎn)生指令

異常產(chǎn)生指令包括兩條:SWI和BKPT。

(1)

SWI——軟中斷指令。

格式:SWI{cond}immed_24

SWI指令用于產(chǎn)生軟中斷,從而實(shí)現(xiàn)從用戶模式切換到管理模式,并將CPSR保存到管理模式下的SPSR中,然后程序跳轉(zhuǎn)到SWI異常入口。

另外,用戶請(qǐng)求的服務(wù)類型由指令中的24位立即數(shù)指定,參數(shù)通過寄存器傳遞;若24位立即數(shù)被忽略,則用戶請(qǐng)求的服務(wù)類型由寄存器R0的數(shù)值決定。

(2)

BKPT——斷點(diǎn)中斷指令。

格式:BKPTimmed_16

BKPT用于產(chǎn)生軟件斷點(diǎn)中斷,供軟件調(diào)試程序使用,用來保存額外的斷點(diǎn)信息。4.1.4Thumb指令集

Thumb指令集是ARM指令集的功能子集,指令長(zhǎng)度為16位,它沒有改變ARM體系底層的程序設(shè)計(jì)模型,只是在該模型上增加了一些限制條件。與32位等價(jià)代碼相比,Thumb指令集在保留了32位代碼優(yōu)勢(shì)的同時(shí),大大節(jié)省了系統(tǒng)的存儲(chǔ)空間。

在編寫Thumb指令時(shí),要先使用偽指令CODE16聲明;而在編寫ARM指令時(shí),使用偽指令CODE32聲明。在ARM指令下,可以通過BX指令跳轉(zhuǎn)到Thumb指令,以切換處理器的工作狀態(tài)。Thumb指令沒有提供訪問CPSR/SPSR寄存器的指令,處理器根據(jù)CPSR中的T位來決定指令類型:當(dāng)T位為0時(shí),指令為ARM指令;當(dāng)T位為1時(shí),指令為Thumb指令。

根據(jù)Thumb指令集的功能可以將其分為兩大類:存儲(chǔ)器訪問指令和數(shù)據(jù)處理指令。由于從功能上來講,Thumb指令是ARM指令的子集,在了解了ARM指令的基礎(chǔ)上很容易理解Thumb指令,所以這里只對(duì)其作一個(gè)簡(jiǎn)單的介紹。

1.存儲(chǔ)器訪問指令

Thumb指令集的存儲(chǔ)器訪問指令包括3類:

(1)單寄存器加載/存儲(chǔ)指令LDR/STR,它可以將R0~R7的任何子集進(jìn)行加載/存儲(chǔ)。同ARM中的LDR/STR指令一樣,也可以通過加后綴B、H、SB、SH實(shí)現(xiàn)對(duì)無符號(hào)字節(jié)、無符號(hào)半字、有符號(hào)字節(jié)和有符號(hào)半字的加載/存儲(chǔ)操作。

(2)批量加載/存儲(chǔ)指令LDMIA/STMIA。加上后綴IA,即在每次傳送完數(shù)據(jù)后,地址加4。

(3)堆棧處理指令PUSH、POP。PUSH實(shí)現(xiàn)低寄存器和可選寄存器LR的入棧操作;POP實(shí)現(xiàn)低寄存器和可選寄存器PC的出棧操作;堆棧地址由SP寄存器設(shè)置。

格式:PUSH{register,[LR]}

POP{register,[PC]}

2.數(shù)據(jù)處理指令

1)數(shù)據(jù)傳送指令

(1)

MOV——數(shù)據(jù)傳送指令。

格式:MOVRd,Rm

(2)

MVN——數(shù)據(jù)求反傳送指令。

格式:MVNRd,Rm;先將Rm取反,再傳送到Rd中

(3)

NEG——數(shù)據(jù)取負(fù)傳送指令。

格式:NEGRd,Rm;先將Rm乘

-1,再傳送到Rd中

2)算術(shù)邏輯指令

算術(shù)邏輯指令包括:加法運(yùn)算指令A(yù)DD、減法運(yùn)算指令SUB、帶進(jìn)位加法指令A(yù)DC、帶進(jìn)位減法指令SBC、乘法指令MUL、邏輯與指令A(yù)ND、邏輯或指令ORR、邏輯異或指令EOR、位清除指令BIC、算術(shù)右移指令A(yù)SR、邏輯左移指令LSL、邏輯右移指令LSR和循環(huán)右移指令ROR。格式與ARM指令中的算術(shù)邏輯指令相同,這里就不再贅述。

3)比較指令

比較指令包括:比較指令CMP、負(fù)數(shù)比較指令CMN和位測(cè)試指令TST。

Thumb指令集也包括跳轉(zhuǎn)指令B、帶返回的跳轉(zhuǎn)指令BL、帶切換的跳轉(zhuǎn)指令BX以及軟中斷指令SWI。

3.?ARM指令集與Thumb指令集的區(qū)別

Thumb指令集大多數(shù)是常用的32位ARM指令的子集,壓縮成16位寬。它沒有協(xié)處理器指令、信號(hào)量指令以及訪問CPSR或SPSR的指令,也沒有乘加指令以及64位乘法指令等,且第二操作數(shù)受到限制。除了條件指令B具有條件執(zhí)行功能外,其他指令均是無條件執(zhí)行。Thumb指令一般是不能預(yù)測(cè)的,而ARM指令是可以預(yù)測(cè)的。Thumb指令用的是雙地址形式(目標(biāo)寄存器和原寄存器是同一個(gè)寄存器),而ARM指令用的是3地址形式。對(duì)Thumb指令來說,訪問寄存器R0~R7是透明的,訪問寄存器R8~R15則是受到限制的(只有MOV和ADD指令能直接訪問寄存器R8~R15),而在ARM狀態(tài)下,對(duì)R0~R15的訪問都是透明的。

4.2.1ARM匯編語言格式簡(jiǎn)介

1.?ARM匯編語言的語句格式

ARM匯編語言的語句格式如下:

{符號(hào)}{指令或偽指令};{注釋}

4.2ARM匯編語言設(shè)計(jì)符號(hào)必須位于一行的代碼開頭,并且不能包含空格。指令或偽指令的助記符必須全部采用大寫或小寫字母,不能大小寫混用。如果一條語句很長(zhǎng),可以將其分為若干行,上下行之間通過上一行末尾的“/”符號(hào)來連接。

2.?ARM匯編語言中的符號(hào)

在ARM匯編語言中使用符號(hào)來代替地址、常量和變量,以增加程序的可讀性。符號(hào)的命名規(guī)則如下:

符號(hào)由大小寫字母、數(shù)字、下劃線組成。

符號(hào)有大小寫之分。

符號(hào)在其作用范圍內(nèi)是唯一的,即在其作用范圍內(nèi)不可以有同名的符號(hào)。

自定義的符號(hào)名不能與系統(tǒng)保留字相同,不能與指令或偽指令同名。另外,符號(hào)代表地址時(shí)又稱為標(biāo)號(hào)。當(dāng)標(biāo)號(hào)以數(shù)字開頭時(shí),其作用范圍就是當(dāng)前段,稱為局部標(biāo)號(hào)。只有局部標(biāo)號(hào)以數(shù)字開頭,其他符號(hào)都不能以數(shù)字開頭。符號(hào)包括變量、常量、地址標(biāo)號(hào)、局部標(biāo)號(hào)等。

1)變量

ARM匯編語言有數(shù)字變量、邏輯變量和字符串變量3種。變量的值在程序的運(yùn)行過程中可以改變,但是類型不能改變。

(1)數(shù)字變量:用于在程序運(yùn)行過程中保存數(shù)字值,但數(shù)字值的大小不能超出數(shù)字變量所能表示的范圍。

(2)邏輯變量:用于在程序運(yùn)行過程中保存邏輯值,邏輯值只有true和false。

(3)字符串變量:用于在程序中保存一個(gè)字符串,字符串的長(zhǎng)度不能超過字符串變量所能表示的范圍。

2)常量

常量是指在程序運(yùn)行過程中不能被改變的量,相對(duì)于變量而言,常量也包括三種類型:數(shù)字常量、邏輯常量和字符串常量。它們都是固定的,不能被程序改變。數(shù)字常量一般是32位的整數(shù),當(dāng)為無符號(hào)數(shù)時(shí)其取值范圍為0~231-1;

當(dāng)為有符號(hào)數(shù)時(shí),其取值范圍為-231~231-1。

3)地址標(biāo)號(hào)

地址標(biāo)號(hào)是表示程序中指令或者數(shù)據(jù)的地址,根據(jù)地址標(biāo)號(hào)的生成方法可以分為絕對(duì)地址標(biāo)號(hào)、基于PC的標(biāo)號(hào)和基于寄存器的標(biāo)號(hào)3種。

(1)絕對(duì)地址標(biāo)號(hào):一個(gè)32位的數(shù)字量,尋址范圍為0~231-1。

(2)基于PC的標(biāo)號(hào):用于表示跳轉(zhuǎn)指令的目標(biāo)地址,或代碼中所嵌入數(shù)據(jù)。PC標(biāo)號(hào)通常位于目標(biāo)指令或數(shù)據(jù)定義偽指令之前。

(3)基于寄存器的標(biāo)號(hào):常用于訪問數(shù)據(jù)段中的數(shù)據(jù),在匯編中用MAP、FIELD和EQU偽指令來定義。

4)局部標(biāo)號(hào)

局部標(biāo)號(hào)主要在局部范圍內(nèi)使用,它由兩部分組成:前面是一個(gè)0~99的數(shù)字,后面跟一個(gè)表示該局部變量作用范圍的符號(hào)。

3.?ARM匯編語言中的表達(dá)式和運(yùn)算符

在ARM匯編語言中也經(jīng)常使用表達(dá)式,表達(dá)式一般由數(shù)值、符號(hào)、括號(hào)、運(yùn)算符組成。其運(yùn)算次序的優(yōu)先級(jí)如下:

括號(hào)運(yùn)算符的優(yōu)先級(jí)最高。

相鄰的單目運(yùn)算符的執(zhí)行順序?yàn)橛捎抑磷螅覇文窟\(yùn)算符的優(yōu)先級(jí)高于其他運(yùn)算符。

優(yōu)先級(jí)相同的雙目運(yùn)算符的執(zhí)行順序?yàn)橛捎抑磷蟆?/p>

常用的表達(dá)式有數(shù)字表達(dá)式、邏輯表達(dá)式和字符串表達(dá)式,與它們相關(guān)的運(yùn)算符及其表達(dá)的含義如表4.3所示。

表4.3常用的表達(dá)式和運(yùn)算符4.2.2ARM匯編語言的程序設(shè)計(jì)

ARM匯編語言以程序段為單位組織代碼,段是相對(duì)獨(dú)立的、不可分割的并且具有獨(dú)立名稱的指令或者數(shù)字序列。段可以分為代碼段和數(shù)據(jù)段,代碼段存放執(zhí)行代碼,數(shù)據(jù)段存放執(zhí)行代碼時(shí)需要用到的數(shù)據(jù)。一個(gè)ARM匯編程序至少應(yīng)該有一個(gè)代碼段,大的程序可以分割成幾個(gè)代碼段和數(shù)據(jù)段,在編譯連接時(shí)最終形成一個(gè)可執(zhí)行的映像文件,該文件包括以下幾個(gè)部分:

一個(gè)或多個(gè)代碼段,代碼段的屬性為只讀。

零個(gè)或多個(gè)包含初始值的數(shù)據(jù)段,數(shù)據(jù)段的屬性為可讀寫。

零個(gè)或多個(gè)不包含初始值的數(shù)據(jù)段,數(shù)據(jù)段的屬性為可讀寫。

鏈接器根據(jù)一定的規(guī)則將各個(gè)段安排在存儲(chǔ)器中相應(yīng)的位置,因此源程序中段之間的相鄰關(guān)系與執(zhí)行的映像文件中段之間的相鄰關(guān)系一般不相同。通過下面一個(gè)簡(jiǎn)單的例子說明ARM匯編語言源程序的基本結(jié)構(gòu)代碼如下:

AREAExample1,CODE,READONLY

ENTRY

START

MOVR0,#0x104

MOVR1,#200

SUBR0,R0,R1

END在上面的例子中,AREA偽指令表明了一個(gè)段的開始,并定義該段的名稱為Example,屬性為代碼段,且只讀。ENTRY偽指令標(biāo)識(shí)程序的入口點(diǎn),ARM程序至少要包含一個(gè)ENTRY。START為地址標(biāo)號(hào)。接下來是指令序列,該指令實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的減法運(yùn)算。程序的末尾為END偽指令,告訴編譯器源文件結(jié)束,每個(gè)匯編程序都必須有一條END偽指令。

在匯編語言中通常會(huì)對(duì)子程序進(jìn)行調(diào)用。子程序的調(diào)用一般是通過BL指令完成的,格式如下:

BL子程序名在執(zhí)行該指令時(shí),首先將子程序的返回地址存放在LR寄存器中,同時(shí)將程序計(jì)數(shù)器PC指向子程序的入口點(diǎn);在子程序執(zhí)行完畢需要返回時(shí),將LR中的返回地址傳送到PC中即可。在調(diào)用子程序的同時(shí),可以通過寄存器R0~R3來完成參數(shù)的傳遞和從子程序返回運(yùn)算結(jié)果。匯編語言的子程序調(diào)用示例如下:

AREAExample1,CODE,READONLY

ENTRY

START

MOVR0,#0x104

MOVR1,#200

SUBR0,R0,R1

BLram_loop

ram_loop;子程序

MOVPC,LR

END

本章主要介紹ARM處理器下C語言編程的優(yōu)化,C語言與匯編語言的混合編程以及ARMC/C++

編譯器的基本知識(shí)。4.3ARMC語言設(shè)計(jì)4.3.1C語言編程技術(shù)

ARM和ThumbC編譯器采用的都是標(biāo)準(zhǔn)ANSIC編譯器,它能夠產(chǎn)生精簡(jiǎn)而有效的機(jī)器指令,但是若能在寫C代碼的時(shí)候注意一些編程技巧,則能夠?qū)Τ绦蜻M(jìn)行進(jìn)一步的優(yōu)化,從而有效地降低C語言編譯后代碼的長(zhǎng)度和執(zhí)行時(shí)間,提高代碼的執(zhí)行效率。下面將介紹幾種ARM處理器下C語言編程效率優(yōu)化的方法。

1.變量的定義

由于ARM采用32位4字節(jié)來存儲(chǔ)數(shù)據(jù),因此在定義變量的時(shí)候一定要注意空間的分布。最好是把所有相同類型的變量放在一起定義,這樣會(huì)避免造成存儲(chǔ)空間的浪費(fèi)。另外,對(duì)于局部變量,盡量使用32位的變量類型。因?yàn)榫幾g器在把局部變量分配給內(nèi)部寄存器時(shí),每個(gè)變量占用一個(gè)32位寄存器,因此使用char、short型變量不但沒有提高程序的執(zhí)行效率,反而會(huì)需要更多指令。

2.除法和求模的優(yōu)化

ARM在硬件上不支持除法指令,編譯器是通過調(diào)用C庫(kù)函數(shù)來實(shí)現(xiàn)除法運(yùn)算的。但直接利用C庫(kù)函數(shù)進(jìn)行除法運(yùn)算,會(huì)消耗較多的軟件運(yùn)行時(shí)間,執(zhí)行速度比較慢,因此應(yīng)盡量避免使用除法和求模運(yùn)算。

(1)在某些程序設(shè)計(jì)中,可以把除法改寫為乘法。如:(x/y)

>

z,在已知y是正數(shù)而且y×z是整數(shù)的情況下,就可以寫為x

>

(z

×

y)。

(2)盡可能使用2的次方作為除數(shù),編譯器使用移位操作完成除法。在程序設(shè)計(jì)中,使用無符號(hào)型的除法要快于符號(hào)型的除法。

(3)對(duì)于求模運(yùn)算也可以采用其他的語句來進(jìn)行替換,例如代碼:

Count=(Count+increment)%size;

可以用以下代碼替換:

Count+=increment;

if(size<=Count)

{

Count-=size;

}

(4)對(duì)于一些特殊的除法和求余運(yùn)算,采用查找表的方法也可以獲得很好的運(yùn)行效果。

3.循環(huán)體的優(yōu)化

(1)如果循環(huán)體內(nèi)存在邏輯判斷,并且循環(huán)次數(shù)很大,最好將邏輯判斷移到循環(huán)體的外面。在多重循環(huán)中應(yīng)將最長(zhǎng)的循環(huán)放在最內(nèi)層,這樣可以減少PC指針從內(nèi)循環(huán)跳到外循環(huán)的次數(shù)。

(2)程序中的循環(huán)結(jié)束條件應(yīng)是“遞減到0”的循環(huán),結(jié)束條件盡量簡(jiǎn)單,以減少指令和寄存器的使用。

(3)如果循環(huán)體至少執(zhí)行一次,則優(yōu)先選用do-while。如果一個(gè)循環(huán)體只循環(huán)幾次,可以將其展開。因?yàn)楫?dāng)循環(huán)展開后,不需要循環(huán)計(jì)數(shù)器和相關(guān)的跳轉(zhuǎn)語句,雖然代碼的長(zhǎng)度有所增加,但是執(zhí)行的效率更高。

4.條件執(zhí)行的優(yōu)化

(1)在ARMC語言程序設(shè)計(jì)中,有符號(hào)變量應(yīng)盡量采用x<0、x>=0、x==0和x!=0的關(guān)系運(yùn)算;對(duì)于無符號(hào)變量應(yīng)采用x==0、x!=0(或者x>0)的關(guān)系運(yùn)算符。編譯器都可以對(duì)條件執(zhí)行進(jìn)行優(yōu)化。

(2)

ARM中的條件執(zhí)行是通過對(duì)運(yùn)算結(jié)果標(biāo)志位進(jìn)行判斷實(shí)現(xiàn)的。在ARMC語言程序設(shè)計(jì)中,條件判斷應(yīng)當(dāng)盡量采用“與0比較”的形式,因?yàn)樵贏RMC語言程序中,如果運(yùn)算結(jié)果是與0作比較,編譯器會(huì)移去比較指令,通過一條帶標(biāo)志位指令實(shí)現(xiàn)運(yùn)算和判斷。

(3)對(duì)于程序設(shè)計(jì)中的條件語句,應(yīng)盡量簡(jiǎn)化if和else判斷條件。與傳統(tǒng)的C語言程序設(shè)計(jì)有所不同,在ARMC語言程序設(shè)計(jì)中,關(guān)系表述中類似的條件應(yīng)該集中在一起,使編譯器能夠?qū)ε袛鄺l件進(jìn)行優(yōu)化。4.3.2C語言與匯編語言混合編程

在嵌入式系統(tǒng)開發(fā)中,目前使用的主要編程語言是C語言和匯編語言。C語言結(jié)構(gòu)好,表達(dá)能力強(qiáng),有大量的支持庫(kù),功能豐富,使用靈活,開發(fā)效率高;但是在一些實(shí)時(shí)控制的場(chǎng)合,匯編語言有著不可替代的作用。匯編語言是一種面向機(jī)器的語言,具有運(yùn)行速度快,占用存儲(chǔ)空間小,可直接對(duì)硬件進(jìn)行控制的特點(diǎn),因此在實(shí)際開發(fā)和軟件編制過程中,我們常常將C和匯編語言進(jìn)行混合編程,充分利用兩種語言的優(yōu)勢(shì),使開發(fā)和編程工作達(dá)到事半功倍的效果。

1.在C語言中內(nèi)嵌匯編

在ARMC語言中內(nèi)嵌匯編使用的標(biāo)記是_asm或asm關(guān)鍵字,用法如下:

_asm

{

instruction[;instruction]

[instruction]

}

asm("instruction[;instruction]");需要注意的問題有:

(1)內(nèi)嵌的匯編語句可以用“;”結(jié)束,也可以用換行符結(jié)束,一行中可以有多個(gè)匯編語句,相互間用分號(hào)分隔,不能跨行書寫;內(nèi)嵌匯編語句的分號(hào)不是注釋的開始,要對(duì)語句進(jìn)行注釋時(shí),應(yīng)使用C語言的注釋。

(2)一般不要直接指定物理寄存器,而應(yīng)讓編譯器進(jìn)行分配;在使用物理寄存器時(shí),不要使用過于復(fù)雜的C語言表達(dá)式,以避免物理寄存器沖突。

(3)

R12和R13可能被編譯器用來存放中間編譯結(jié)果,R0~R3、R12和R14可能在計(jì)算表達(dá)式值時(shí)用于子程序調(diào)用,因此要避免直接使用這些物理寄存器。

2.在匯編程序中訪問C程序變量

匯編程序可以通過地址間接地訪問C程序中聲明的全局變量。具體訪問方法是:首先,使用IMPORT偽指令聲明該全局變量;用LDR指令讀取該全局變量的內(nèi)存地址,然后根據(jù)該數(shù)據(jù)的類型使用相應(yīng)的LDR指令讀取該全局變量的值,再使用相應(yīng)的STR指令修改后將值賦予該全局變量。程序如下:

AREAasmfile,CODE,READONLY

EXPORTasmAdd

IMPORTglobV1 ;聲明變量

asmAdd

LDRR0,=globV1 ;將內(nèi)存地址讀入到R0中

LDRR1,[R0] ;將數(shù)據(jù)讀入到R1中

MOVR2,#2

MULR3,R1,R2

STRR3,[R0] ;修改后將值賦予變量

MOVPC,LR

END

3.匯編語言與C語言之間的相互調(diào)用

匯編語言與C語言在進(jìn)行相互調(diào)用的時(shí)候要遵守相應(yīng)的ATPCS規(guī)則,以保證程序調(diào)用時(shí)參數(shù)的正確傳送。

1)在C程序中調(diào)用匯編程序

在C程序中調(diào)用匯編程序,一是要在C程序中聲明函數(shù)原型,并加extern關(guān)鍵字;二是要在匯編程序中使用EXPORT偽指令導(dǎo)出函數(shù)名,并用該函數(shù)名作為匯編代碼段的標(biāo)識(shí),以使該代碼段可以被其他程序調(diào)用,最后用MOVPC,LR返回。

2)在匯編程序中調(diào)用C程序

在匯編程序中調(diào)用C程序,

需要在匯編中使用偽指令I(lǐng)MPORT聲明將要調(diào)用的C程序,然后將C程序的代碼放在一個(gè)獨(dú)立的C文件中進(jìn)行編譯,剩下的工作由連接器來處理。4.3.3ARMC/C++?編譯器

ARMC/C++

編譯器可以被使用在UNIX和Windows/MS-DOS環(huán)境下。ARMC++

編譯器可以編譯成多種格式的C/C++

源代碼,其中包括ANSIC、EC++

和C++。表4.4列出的是ARM中常見的C/C++

編譯器。

表4.4ARM中常見的C/C++

編譯器在介紹這些編譯器之前,必須要明白什么是匯編/編譯過程。所謂匯編/編譯過程就是將用ANSIC或匯編語言編寫的程序編譯成16位的Thumb或32位的ARM指令代碼。匯編和編譯工作是由集成到ADS中的開發(fā)工具完成的,用戶也可以通過ADS提供的命令行界面直接調(diào)用它們。了解這些開發(fā)工具,將有助于開發(fā)出高質(zhì)量的產(chǎn)品。

1.?ARMC編譯器armcc

armcc編譯器用于將遵循ANSIC編寫的程序編譯成32位的ARM指令代碼,它通過了PlumHallCValidationSuite為ANSIC設(shè)計(jì)的一致性測(cè)試。

armcc編譯器最基本的用法為

armcc[options]file1file2…filen

其中,

options:編譯器所需要的選項(xiàng),它控制了編譯的過程和生成文件的屬性。

file1,file2…filen:需要處理的源文件名字。

表4.5常用的options選項(xiàng)對(duì)于詳細(xì)的armcc的選項(xiàng)和用法,可以在ADS命令控制臺(tái)環(huán)境下,使用armcc–help命令來查看。

ARMC/C++編譯器通過文件后綴名來區(qū)分文件的類型。ARMC/C++編譯器支持和產(chǎn)生以下幾種格式的文件。

filename.c:ARMC編譯器將*.C格式的文件作為源文件;ARMC++編譯器將*.C、*.CPP、*.CP、*.C++、*.CC格式的文件都作為源文件。

filename.h:頭文件。

filename.o:編譯器輸出的ELF格式的目標(biāo)文件。

filename.s:ARM或者Thumb格式的匯編代碼文件。

filename.lst:錯(cuò)誤及警告信息的列表文件。

ARM編譯器支持的各種語法pragmas及其含義如表4.6所示。

表4.6ARM編譯器支持的各種語法及其含義

2.?ThumbC編譯器tcc

tcc編譯器將ANSIC源代碼編譯成16位的Thumb指令代碼,其用法類似于armcc。該編譯器也通過了PlumHallCValidationSuite為ANSIC設(shè)計(jì)的一致性測(cè)試。

3.匯編器armasm

armasm是ARM和Thumb的匯編器,它對(duì)用ARM匯編語言和Thumb匯編語言編寫的源代碼進(jìn)行匯編。

4.?ARMC++編譯器armcpp

armcpp編譯器用來將ISOC++

或EC++

編譯成32位的ARM指令代碼。

5.?ThumbC++編譯器tcpp

tcpp編譯器用來將ISOC++或EC++編譯成16位的Thumb指令代碼。

對(duì)于初學(xué)者來說,在ARM入門過程中,可以只對(duì)這些命令工具做一些了解,不必花太多的精力來研究每一條指令的選項(xiàng)或者用法。ADS中提供的GUI界面可以滿足大多數(shù)用戶配置匯編/編譯過程的要求。

本節(jié)主要介紹ARM開發(fā)軟件ADS(ARMDeveloperSuite)。通過學(xué)習(xí)如何在CodeWarriorIDE集成開發(fā)環(huán)境下編寫、編譯一個(gè)示例工程,使讀者掌握在ADS軟件平臺(tái)下開發(fā)用戶應(yīng)用程序的方法。本節(jié)還描述了使用AXD調(diào)試工程的方法,使讀者對(duì)于調(diào)試工程有個(gè)初步的理解,為進(jìn)一步使用和掌握調(diào)試工具起到拋磚引玉的作用。4.4ADS開發(fā)平臺(tái)4.4.1ADS開發(fā)平臺(tái)的特點(diǎn)

ARMADS的全稱為ARMDeveloperSuite,是ARM公司推出的新一代ARM集成開發(fā)工具。現(xiàn)在ADS的最新版本是1.2,它取代了早期的ADS1.1和ADS1.0。ADS可以安裝在WindowsNT/2000/98/95/XP等操作系統(tǒng)中使用。

ADS由命令行開發(fā)工具、ARM實(shí)時(shí)庫(kù)、GUI開發(fā)環(huán)境(CodeWarrior和AXD)、實(shí)用程序和支持軟件組成。有了這些部件,用戶就可以為ARM系列的RISC處理器編寫和調(diào)試自己開發(fā)的應(yīng)用程序了。4.4.2CodeWarrior軟件的使用方法

CodeWarriorforARM是一套集編輯、編譯、連接于一體的集成開發(fā)工具,它充分發(fā)揮了ARMRISC的優(yōu)勢(shì),使產(chǎn)品開發(fā)人員能夠很好地應(yīng)用尖端的片上系統(tǒng)技術(shù)。該工具是專為基于ARMRISC的處理器而設(shè)計(jì)的,它可加速并簡(jiǎn)化嵌入式開發(fā)過程中的每一個(gè)環(huán)節(jié),使得開發(fā)人員只需通過一個(gè)集成軟件開發(fā)環(huán)境就能研制出ARM產(chǎn)品,在整個(gè)開發(fā)周期中,開發(fā)人員無需離開CodeWarrior開發(fā)環(huán)境,因此節(jié)省了在操作工具上所花的時(shí)間,使得開發(fā)人員有更多的精力投入到代碼編寫上來。

CodeWarriorIDE為用戶提供了以下功能:

(1)源代碼編輯器,集成在CodeWarriorIDE的瀏覽器中,能夠根據(jù)語法格式,使用不同的顏色顯示代碼。

(2)源代碼瀏覽器,它保存了在源碼中定義的所有符號(hào),能夠使用戶在源碼中快速方便的跳轉(zhuǎn)。

(3)查找和替換功能,用戶可以在多個(gè)文件中,利用字符串通配符,進(jìn)行字符串的搜索和替換。

(4)文件比較功能,方便用戶比較路徑中的不同文本文件的內(nèi)容。

1.建立一個(gè)工程

工程將多個(gè)源碼文件組織在一起,并決定最終生成文件的格式、存放路徑等。

建立工程的步驟如下:

(1)首先在CodeWarrior下新建一個(gè)工程。方法有兩種,可以在工具欄中單擊New按鈕,也可以選擇File→New命令,彈出的對(duì)話框如圖4.2所示。圖4.2在CodeWarrior下新建一個(gè)工程my_first該對(duì)話框?yàn)橛脩籼峁┝?種可選的工程類型:

ARMExcutableImage:用于由ARM指令的代碼生成一個(gè)ELF格式的可執(zhí)行的映像文件。

ARMObjectLibrary:用于由ARM指令的代碼生成一個(gè)armar格式的目標(biāo)文件庫(kù)。

EmptyProject:用于創(chuàng)建一個(gè)不包含任何庫(kù)或者源文件的工程。

MakefileImporterWizard:用于將VisualC的nmake或者GNUmake文件轉(zhuǎn)入到CodeWarriorIDE工程文件。

ThumbARMExcutableImage:用于由ARM指令和Thumb指令的混和代碼生成一個(gè)可執(zhí)行的ELF格式的映像文件。

ThumbExcutableimage:用于由Thumb指令創(chuàng)建一個(gè)可執(zhí)行的ELF格式的映像文件。

ThumbObjectLibrary:用于由Thumb指令的代碼生成一個(gè)armar格式的目標(biāo)文件庫(kù)。我們?cè)谶@里選擇ARMExecutableImage,在“Projectname:”中輸入工程文件名,本例以ADS1.2中自帶的example中的sorts為例,輸入“my_first”,點(diǎn)擊“Location:”文本框的“Set”按鈕,瀏覽選擇想要保存該工程的路徑(本例為“D:\work”),將這些設(shè)置好之后,點(diǎn)擊“確定”,即可創(chuàng)建一個(gè)新的名為“my_first”的工程。

這個(gè)時(shí)候會(huì)出現(xiàn)“my_first.mcp”窗口,如圖4.3所示,同時(shí)會(huì)在D:\work目錄下創(chuàng)建一個(gè)工程目錄my_first,而my_first.mcp會(huì)出現(xiàn)在D:\work\myfirst目錄中,如圖4.4所示。

圖4.3新建的my_first.mcp文檔窗口的工作區(qū)

圖4.4新建工程的保存目錄在新建的my_first.mcp文檔窗口中,大致可以分為四個(gè)區(qū)域,如圖4.3所示。

在出現(xiàn)的my_first.mcp的窗口中,可以看到默認(rèn)的目標(biāo)調(diào)試環(huán)境是DebugRel,右側(cè)的下拉列表框中還有另外兩個(gè)可用的目標(biāo)調(diào)試環(huán)境,分別為Release和Debug。

3個(gè)目標(biāo)調(diào)試系統(tǒng)的含義分別為:

DebugRel:在生成

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論