微機(jī)原理與嵌入式接口技術(shù)課件:Cortex-M3 的指令系統(tǒng)與匯編程序設(shè)計(jì)_第1頁
微機(jī)原理與嵌入式接口技術(shù)課件:Cortex-M3 的指令系統(tǒng)與匯編程序設(shè)計(jì)_第2頁
微機(jī)原理與嵌入式接口技術(shù)課件:Cortex-M3 的指令系統(tǒng)與匯編程序設(shè)計(jì)_第3頁
微機(jī)原理與嵌入式接口技術(shù)課件:Cortex-M3 的指令系統(tǒng)與匯編程序設(shè)計(jì)_第4頁
微機(jī)原理與嵌入式接口技術(shù)課件:Cortex-M3 的指令系統(tǒng)與匯編程序設(shè)計(jì)_第5頁
已閱讀5頁,還剩164頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

Cortex-m3的指令系統(tǒng)

與匯編程序設(shè)計(jì)3.1CM3指令的結(jié)構(gòu)3.2CM3指令的尋址方式3.3CM3指令集3.4ARM匯編程序設(shè)計(jì)基礎(chǔ)組習(xí)題3

本章要點(diǎn)

☆CM3指令的結(jié)構(gòu)

☆CM3指令的尋址方式

☆CM3指令集

☆A(yù)RM匯編程序設(shè)計(jì)基礎(chǔ)

3.1CM3指令的結(jié)構(gòu)

3.1.1Thumb2指令集CUP依靠指令來完成計(jì)算和控制任務(wù),每款CUP在設(shè)計(jì)時(shí)就規(guī)定了一系列與其硬件電路相匹配的指令系統(tǒng)。指令系統(tǒng)的強(qiáng)弱是CUP的重要指標(biāo),是提高微處理器效率的最有效工具之一。

ARM指令集為32位指令集,可以實(shí)現(xiàn)ARM架構(gòu)下的所有功能。Thumb指令集是對(duì)32位ARM指令集的擴(kuò)充,它的目標(biāo)是為了實(shí)現(xiàn)更高的代碼密度。Thumb指令集實(shí)現(xiàn)的功能只是32位ARM指令集的子集,它僅僅把常用的ARM指令壓縮成16位的指令編碼方式。

Thumb-2技術(shù)改善了Thumb指令集的性能,它在原有的Thumb指令的基礎(chǔ)上進(jìn)行了如下的擴(kuò)充:增加了一些新的16位Thumb指令來改進(jìn)程序的執(zhí)行流程,增加了一些新的32位Thumb指令以實(shí)現(xiàn)一些ARM指令的專有功能,解決了之前Thumb指令集不能訪問協(xié)處理器、特權(quán)指令和特殊功能指令的局限。Thumb-2指令集可以實(shí)現(xiàn)所有的功能,這樣就不需要在ARM/Thumb狀態(tài)之間反復(fù)切換了,代碼密度和性能得到了顯著的提高,但值得注意的是Thumb-2并不支持32位ARM指令集。

如圖3.1所示,Cortex-m3處理器支持Thumb2指令集,但并不支持所有的Thumb-2指令,架構(gòu)于ARMv7上的Cortex-m3只要求實(shí)現(xiàn)Thumb2的一個(gè)子集。圖3.1Thumb2指令集與Thumb指令集的關(guān)系

例程3.1寄存器相加。

3.1.2CM3指令的格式

指令是構(gòu)成程序的基本單元,程序是指令的有序集合。指令的基本格式如下:

<指令助記符>{<執(zhí)行條件>}{S}{P}<目標(biāo)寄存器>,<操作數(shù)1的寄存器>{,<操作數(shù)2>}<pcode>{<cond>}

{S}

{P}<Rd>,<Rn>{,<operand2>}其中,<>內(nèi)的項(xiàng)是必需的,{

}內(nèi)的項(xiàng)是可選的。如<opcode>指令助記符是必須書寫的;{cond}為指令執(zhí)行條件,是可選項(xiàng),若不書寫則使用默認(rèn)的條件AL(無條件執(zhí)行)。

opcode:指令助記符,如LDR、STR等,表示了該指令需要執(zhí)行的動(dòng)作。

cond:條件后綴,當(dāng)后綴條件滿足時(shí)指令被執(zhí)行,如EQ、NR等,參考表3.1。

S:S后綴,表明是否更新APSR狀態(tài)寄存器的值,書寫時(shí)指令執(zhí)行結(jié)果影響APSR。

P:P后綴,指定指令的編碼類型,其定義如下:

(1)當(dāng)指定P為.N時(shí),則該指令指定編譯為16位Thumb2編碼指令,且其前提是該指令支持16位長度編碼,若不支持將導(dǎo)致編譯錯(cuò)誤。

(2)當(dāng)指定P為.W時(shí),則該指令指定編譯為32位Thumb2編碼指令,且其前提是該指令支持32位長度編碼,若不支持將導(dǎo)致編譯錯(cuò)誤。

(3)若未指定指令編碼類型,則由編譯器自動(dòng)選擇指令的類型,且根據(jù)指令存在的編碼類型優(yōu)先選擇16位指令,實(shí)際編程時(shí)一般不指定指令的編碼類型。

例程3.2指令格式舉例。

3.1.3CM3指令的后綴

在Cortex-m3處理器中,指令可以帶后綴,后綴主要有條件后綴、S后綴和P后綴,S后綴和P后綴前面已介紹過,這里主要介紹條件后綴。

例程3.3條件后綴應(yīng)用示例。

在Coetex-m3中,下列指令將會(huì)更新APSR中的標(biāo)志位:

(1)16位算術(shù)邏輯指令;

(2)32位帶S后綴的算術(shù)邏輯指令;

(3)比較指令和測(cè)試指令;

(4)直接操作APSR指令(MSR指令)。

3.2CM3指令的尋址方式

從存放的物理位置來看,操作數(shù)存放在程序空間、寄存器空間和主存儲(chǔ)器空間三處地方,如圖3.2所示。所謂尋址就是尋找操作數(shù)的方式,為方便地尋找存放于不同空間的操作數(shù),產(chǎn)生了諸多的尋址方式。

3.2.1立即操作數(shù)的尋址

立即操作數(shù)作為指令的一個(gè)部分存在于程序空間。在取出指令的同時(shí)也就取出了這個(gè)可以立即使用的操作數(shù)(也稱為立即數(shù))。立即數(shù)實(shí)際上就是程序中的常數(shù),用于給變量賦初值。除非修改程序,常數(shù)性質(zhì)的立即數(shù)是不會(huì)發(fā)生變化的,這種尋址方式通常稱為立即尋址。

例程3.4立即尋址應(yīng)用示例。

說明:前綴“#”表示立即數(shù),“0x”表示16進(jìn)制數(shù)值。

從表3.2可以看出,ARM將32位指令分為兩個(gè)部分。

立即數(shù)要滿足一定的生成規(guī)則:即每個(gè)立即數(shù)由一個(gè)8位的常數(shù)循環(huán)右移偶數(shù)位得到,其中循環(huán)右移的位數(shù)用一個(gè)4位二進(jìn)制數(shù)的兩倍表示。如果立即數(shù)記作<immediate>,8位常數(shù)記作immed_8,4位的循環(huán)右移值記作rotate_imm,則有

ARM匯編編譯器按照下面的規(guī)則生成立即數(shù)的編碼。

(1)當(dāng)立即數(shù)數(shù)值在0~0xFF范圍時(shí),rotate_imm=

0。

(2)其他情況下,匯編編譯器選擇使rotate_imm數(shù)值最小的編碼方式。

判斷一個(gè)數(shù)是否為合法的立即數(shù),首先將這個(gè)數(shù)轉(zhuǎn)換為32位的十六進(jìn)制形式,例如

218=0xDA=0x0000_00DA,并按下面規(guī)則判斷。

(1)除零外,僅有一位數(shù)的為合法立即數(shù)。

(2)除零外,僅有兩位數(shù),并且相鄰(包括首尾,如0x1000000A)的為合法立即數(shù)。

(3)除零外,僅有三位數(shù),并且相鄰(包括中間有0,例如0x10800000;包括首尾相鄰,例如0x14000003),這三位數(shù)中,最高位取值僅能為1、2、3,最低位取值僅能為4、8、C,中間位0x0~0xF。這種組合的為合法立即數(shù)。

除以上三種外,其他基本是無法滿足生成規(guī)則的非法立即數(shù)。

3.2.2寄存器操作數(shù)的尋址

1.寄存器尋址

當(dāng)操作數(shù)位于寄存器中,指令中的地址碼字段指出的是寄存器編號(hào),指令執(zhí)行時(shí)直接取出寄存器值來操作。寄存器尋址方式是一種簡單快捷的尋址方式,執(zhí)行效率高,源和目的操作數(shù)都可以位于寄存器中。

2.寄存器移位尋址

寄存器移位尋址是Cortex-M3指令集特有的尋址方式。

可用的移位操作如下:

·LSL:邏輯左移,寄存器中數(shù)據(jù)位低端空出的位補(bǔ)0。

·LSR:邏輯右移,寄存器中數(shù)據(jù)位高端空出的位補(bǔ)0。

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

·ROR:循環(huán)右移(RotateRight),從數(shù)據(jù)位低端移出的位填入數(shù)據(jù)位高端空出的位。

·RRX:帶擴(kuò)展的循環(huán)右移,操作數(shù)右移一位,高端空出的位用原C標(biāo)志值填充。

算術(shù)左移與邏輯左移的規(guī)則完全相同。各種移位操作如圖3.3所示。圖3.3移位操作示意圖

3.多寄存器尋址

多寄存器尋址即一次可傳送幾個(gè)寄存器值,允許一條指令傳送16個(gè)寄存器的任何子集或所有寄存器。

例程3.7多寄存器尋址應(yīng)用示例。

3.2.3存儲(chǔ)器操作數(shù)的尋址

1.寄存器間接尋址

指令中的地址碼給出的是一個(gè)通用寄存器的編號(hào),所需的操作數(shù)保存在寄存器指定地址的存儲(chǔ)單元中,即寄存器為操作數(shù)的地址指針。

例程3.8寄存器間接尋址應(yīng)用示例。

2.基址尋址

1)基址尋址

基址尋址就是將基址寄存器的內(nèi)容與指令中給出的偏移量相加,形成操作數(shù)的有效地址。

例程3.9基址尋址應(yīng)用示例。

2)相對(duì)尋址

相對(duì)尋址是基址尋址的一種變通。由程序計(jì)數(shù)器(PC)提供基準(zhǔn)地址,指令中的地址碼字段作為偏移量,兩者相加后得到的地址即為操作數(shù)的有效地址。

例程3.10相對(duì)尋址應(yīng)用示例。

3.堆棧尋址

堆棧是按照“先進(jìn)后出”規(guī)則管理的存儲(chǔ)器區(qū)域,無論是傳統(tǒng)的ARM7還是現(xiàn)在的Cortex-m3,對(duì)堆棧操作都是通過堆棧指針(SP)來進(jìn)行的,隨著堆棧內(nèi)容的增減,堆棧指針也進(jìn)行相應(yīng)的移動(dòng)。如圖3.4所示,一般情況下對(duì)于嵌入式處理器支持兩種堆棧指針的移動(dòng)方向,即“堆棧的生長方向”。圖3.4堆棧的生長方向

向上生長:在向堆棧寫入數(shù)據(jù)后,堆棧指針的值變大,也就是向高地址方向生長,稱之為“遞增堆?!?。

向下生長:在向堆棧寫入數(shù)據(jù)后,堆棧指針的值變小,也就是向低地址方向生長,稱之為“遞減堆?!薄?/p>

除了要考慮堆棧指針的增長方向之外,還要考慮堆棧指針指向的存儲(chǔ)單元是否已經(jīng)保存有堆棧數(shù)據(jù),或者說在入棧時(shí)是否可以直接向堆棧指針指向的存儲(chǔ)單元寫入數(shù)據(jù)。一般的ARM處理器將此種情況分為“滿堆?!焙汀翱斩褩!?,如圖3.5所示。圖3.5堆棧的空滿特性

滿堆棧:堆棧指針指向最后壓入棧的有效數(shù)據(jù)項(xiàng),此種堆棧的入棧操作要先調(diào)整指針再寫入數(shù)據(jù)。

空堆棧:堆棧指針指向下一個(gè)待壓入數(shù)據(jù)的空位置,此種堆棧的入棧操作要先寫入數(shù)據(jù)再調(diào)整指針。

綜合前面的堆棧生長方向和空滿特性,一共可以得到四種堆棧類型,分別為:

滿遞增:堆棧通過增大存儲(chǔ)器的地址向上增長,棧頂指向含有效數(shù)據(jù)的最高地址;

空遞增:堆棧通過增大存儲(chǔ)器的地址向上增長,棧頂指向堆棧上的第一個(gè)空位置;

滿遞減:堆棧通過減小存儲(chǔ)器的地址向下增長,棧頂指向含有效數(shù)據(jù)的最低地址;

空遞減:堆棧通過減小存儲(chǔ)器的地址向下增長,棧頂指向堆棧下的第一個(gè)空位置。

例程3.11堆棧尋址應(yīng)用示例。

3.3CM3指令集

3.3.1存儲(chǔ)器訪問指令Cortex-m3處理器對(duì)存儲(chǔ)器的訪問只能通過加載和存儲(chǔ)指令來實(shí)現(xiàn)。加載指令LDR是把存儲(chǔ)器中的內(nèi)容加載到寄存器中,而存儲(chǔ)指令STR則是把寄存器內(nèi)容存儲(chǔ)至存儲(chǔ)器中,其指令傳送過程中的數(shù)據(jù)類型實(shí)現(xiàn)了字節(jié)、半字、字和雙字的操作。此外,多寄存器加載和存儲(chǔ)指令可以實(shí)現(xiàn)一條指令加載和存儲(chǔ)多個(gè)寄存器的內(nèi)容,且大大提高數(shù)據(jù)操作效率。

例如通常情況下,如果要讀取4個(gè)地址連續(xù)的存儲(chǔ)單元的內(nèi)容,若采用LDR指令,可能需要8個(gè)周期,而若采用多寄存器的LDM加載指令,則只需要5個(gè)周期。Thumb-2存儲(chǔ)器訪問指令如表3.3所示。

1.LDR和STR指令——加載和存儲(chǔ)指令

LDR指令用于從存儲(chǔ)器中讀取數(shù)據(jù)放入寄存器中;STR指令用于將寄存器中的數(shù)據(jù)保存到存儲(chǔ)器。

例程3.12常用指令。

地址偏移量可以有以下三種格式:

(1)立即數(shù)。立即數(shù)可以是一個(gè)無符號(hào)的數(shù)值,這個(gè)數(shù)據(jù)可以加到基址寄存器,也可以從基址寄存器中減去這個(gè)數(shù)值。

(2)寄存器。寄存器中的數(shù)值可以加到基址寄存器中,也可以從基址寄存器中減去這個(gè)數(shù)值。

(3)寄存器及移位常數(shù)。寄存器移位后的值可以加到基址寄存器,也可以從基址寄存器中減去這個(gè)數(shù)值。

按照尋址方式的地址計(jì)算方法分,加載和存儲(chǔ)指令可以有以下四種形式。

(1)零偏移。Rn的值作為傳送數(shù)據(jù)的地址,即地址偏移量為0。

例程3.16零偏移應(yīng)用示例。

(2)前索引偏移。在數(shù)據(jù)傳送之前,將偏移量加到Rn中,其結(jié)果作為數(shù)據(jù)傳送的存儲(chǔ)地址。若使用后綴“!”,則結(jié)果回寫到Rn中,且Rn的值不允許為R15。

例程3.17前索引偏移應(yīng)用示例。

(3)后索引偏移。Rn的值用做傳送數(shù)據(jù)的存儲(chǔ)地址。在數(shù)據(jù)傳送后,將偏移量與Rn相加,結(jié)果寫回Rn中,Rn不允許是R15。

例程3.18后索引偏移應(yīng)用示例。

(4)程序相對(duì)偏移。程序相對(duì)偏移是前索引形式的另一個(gè)版本。匯編器由PC寄存器計(jì)算偏移量,并將PC寄存器作為Rn生成前索引指令。不能使用后綴“!”。

例程3.19程序相對(duì)偏移應(yīng)用示例。

2.LDM和STM指令——多寄存器加載/存儲(chǔ)指令

LDM/STM的主要用途是較大數(shù)據(jù)量的復(fù)制、參數(shù)傳遞等。其常用的指令主要有:

指令支持的模式說明:

以上四種傳輸模式都是小端模式,其傳輸都是高地址數(shù)據(jù)加載到高寄存器,低地址數(shù)據(jù)加載到低寄存器,高寄存器存儲(chǔ)到高地址,低寄存器存儲(chǔ)到低地址。

指令格式中,寄存器Rn為基址寄存器,裝有傳送數(shù)據(jù)的初始地址,Rn不允許為R15;后綴“!”表示最后的地址回寫到Rn中。寄存器reglist

可包含多于一個(gè)寄存器或包含寄存器范圍,使用“,”分開,如{R1,R2,R6-R9},寄存器由小到大排列。

例程3.20多寄存器傳送指令應(yīng)用示例。

多寄存器傳送指令示意圖如圖3.6所示,其中R1為指令執(zhí)行前的基址寄存器,R1′則為指令執(zhí)行完后的基址寄存器。圖3.6多寄存器傳送示意

STM/LDM與PUSH/POP的區(qū)別:

(1)STM/LDM能對(duì)任意的地址空間進(jìn)行操作,而PUSH/POP只能對(duì)堆棧空間進(jìn)行操作;

(2)STM/LDM同時(shí)支持向上和向下兩種生長方式,而PUSH/POP只能支持向上生長;

(3)當(dāng)兩對(duì)指令的操作數(shù)都為SP時(shí),STM/LDM可以選擇是否回寫修改SP,而PUSH/POP指令會(huì)自動(dòng)修改SP值。

3.3.2數(shù)據(jù)處理運(yùn)算指令

數(shù)據(jù)處理運(yùn)算指令可分為以下幾類:數(shù)據(jù)傳送指令,算術(shù)邏輯運(yùn)算指令,位段處理指令,字節(jié)序反轉(zhuǎn)指令,有符號(hào)擴(kuò)展指令,比較指令以及乘除法和飽和運(yùn)算指令。

以下的指令列表中,僅支持32位編碼的指令,其后綴.W可以省略。各個(gè)指令列表中上標(biāo)有以下含義。

[1]表示指令中的參數(shù)目的寄存器RD如果被忽略,則Rn將變成目的寄存器。

[2]表示指令中的參數(shù)lsb,其取值范圍為0≤lsb≤31;參數(shù)width,其取值范圍為:

1≤width≤(32-lsb)。

[3]表示指令中的參數(shù)rotation,其取值只能為ROR#8、ROR#16、ROR#24中的一個(gè)。

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

MOV指令可以用于寄存器間的數(shù)據(jù)傳輸,也能用于加載立即數(shù)。Thumb-2數(shù)據(jù)傳送指令如表3.4所示。

例程3.21數(shù)據(jù)傳送指令應(yīng)用示例。

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

算術(shù)邏輯運(yùn)算指令主要包括加法指令、減法指令以及移位操作指令。Thumb-2算術(shù)邏輯運(yùn)算指令如表3.5所示。

例程3.22算術(shù)邏輯運(yùn)算指令應(yīng)用示例。

3.位段處理指令

位段處理指令主要包括位段清零、位段插入以及位反轉(zhuǎn)等指令,其對(duì)位處理特別是I/O處理的效率比較高。Thumb-2位段處理指令如表3.6所示。

4.字節(jié)序反轉(zhuǎn)指令

字節(jié)序反轉(zhuǎn)指令專門服務(wù)于小端模式和大端模式的轉(zhuǎn)換,最常見于網(wǎng)絡(luò)應(yīng)用程序中(網(wǎng)絡(luò)字節(jié)序是大端,主機(jī)字節(jié)序常是小端的)。Thumb-2字節(jié)序反轉(zhuǎn)指令如表3.7所示。

例程3.24字節(jié)序反轉(zhuǎn)指令應(yīng)用示例(假設(shè)此處的R2=0x12345687)。

5.有符號(hào)擴(kuò)展指令

有符號(hào)擴(kuò)展指令主要包括有符號(hào)擴(kuò)展一個(gè)字節(jié)、有符號(hào)擴(kuò)展一個(gè)半字以及相應(yīng)的無符號(hào)擴(kuò)展指令,主要用于提取字中的某個(gè)字節(jié)信息或半字信息,是為優(yōu)化C語言的強(qiáng)制類型轉(zhuǎn)換而設(shè)的,可把數(shù)據(jù)寬度轉(zhuǎn)換成處理器喜歡的32位長度。Thumb-2有符號(hào)擴(kuò)展指令如表3.8所示。

例程3.25有符號(hào)擴(kuò)展指令應(yīng)用示例(假設(shè)此處的R2=0x12348756)。

6.比較指令

比較指令主要包括比較指令和測(cè)試指令。該類指令自動(dòng)更新APSR的標(biāo)志位。由于其用法簡單,在此不再做詳細(xì)介紹。Thumb-2比較指令如表3.9所示。

7.硬件乘除法和飽和運(yùn)算指令

硬件乘除法指令主要包括乘加、乘減指令和飽和運(yùn)算指令,并能產(chǎn)生64位積。Thumb-2硬件乘除法和飽和運(yùn)算指令如表3.10所示。

例程3.26硬件乘除法指令應(yīng)用示例。

3.3.3分支轉(zhuǎn)移指令

在Cortex-M3中有兩種方法可以實(shí)現(xiàn)程序的跳轉(zhuǎn),一種是使用分支轉(zhuǎn)移指令實(shí)現(xiàn),另一種則是向PC寄存器直接賦值實(shí)現(xiàn)。Thumb-2分支轉(zhuǎn)移指令如表3.11所示,主要包括B轉(zhuǎn)移指令、比較轉(zhuǎn)移指令、IF-THEN指令塊和查表轉(zhuǎn)移指令等。以上的指令列表中僅支持32位編碼的指令,其后綴.W可以省略。

1.B

轉(zhuǎn)移指令

B

指令是跳轉(zhuǎn)到指定的地址執(zhí)行程序,若是帶鏈接的B指令,則還需要將B

指令的下一條指令地址拷貝到LR

鏈接寄存器中,然后跳轉(zhuǎn)到指定地址運(yùn)行程序。

2.比較轉(zhuǎn)移指令

比較轉(zhuǎn)移指令是根據(jù)比較寄存器的內(nèi)容來決定是否進(jìn)行程序的跳轉(zhuǎn)轉(zhuǎn)移。

3.IF-THEN指令塊

IT(F-THEN)指令塊是圍起一個(gè)指令塊,塊里面最多可以有四條指令,且圍起來的指令必須都是條件執(zhí)行的。

T指令的使用形式如下:

IT指令并不影響APSR的標(biāo)志位,且其指令塊中不允許有任何的程序跳轉(zhuǎn)指令,除了出現(xiàn)異常返回。另外IT

指令塊中不允許存在更新APSR標(biāo)志的指令,因此指令塊中不可以包含CMP、CMN

和TST

指令以及含有更新APSR標(biāo)志的指令形式。

例程3.29IT指令應(yīng)用示例。

4.查表轉(zhuǎn)移指令

查表轉(zhuǎn)移指令TBB

和TBH分別用于從一個(gè)字節(jié)/半字?jǐn)?shù)組表中查找轉(zhuǎn)移地址。

例程3.30查表轉(zhuǎn)移指令應(yīng)用示例。

3.3.4其他指令

Cortex-M3的其他指令如表3.12所示。

1.系統(tǒng)服務(wù)指令

系統(tǒng)服務(wù)指令主要包括軟中斷指令、斷點(diǎn)指令、CPS指令和操作特殊功能寄存器指令。

2.睡眠控制指令

WFI:該指令等待中斷異常發(fā)生。程序運(yùn)行該指令后程序掛起,不再繼續(xù)執(zhí)行,直到發(fā)生中斷異常喚醒CUP。

WFE:該指令等待事件喚醒,用于多核的處理器系統(tǒng)中。

SEV:該指令發(fā)送事件喚醒CUP,主要用于多核的處理器系統(tǒng)中。

3.同步隔離指令

DMB:僅當(dāng)所有在它前面的存儲(chǔ)器訪問都執(zhí)行后,才提交它后面的存儲(chǔ)器訪問動(dòng)作。

DSB:僅當(dāng)所有在它前面的存儲(chǔ)器訪問都執(zhí)行完畢后,才執(zhí)行它后面的指令。

ISB:清空流水線緩沖區(qū),以保證所有在它前面的指令都執(zhí)行完畢之后,才執(zhí)行它后面的指令。

3.3.5偽指令

偽指令不是指令集中的指令,但是可以像其他ARM指令一樣使用,只是在匯編時(shí)將這些偽指令解釋為相應(yīng)指令的組合。Cortex-M3的偽指令如表3.13所示。

1.ADR——小范圍地址讀取偽指令

ADR指令將基于PC相對(duì)偏移的地址值讀取到寄存器中。其偏移量必須是正數(shù)并小于1KB。在用ADR

偽指令將一個(gè)地址裝載到一個(gè)寄存器時(shí),不是裝載地址的絕對(duì)值,而是裝載地址和PC寄存器的差值,即相對(duì)地址。

2.LDR——大范圍地址讀取偽指令

LDR偽指令用于加載32位立即數(shù)或一個(gè)地址值到指定寄存器。且如果匯編器發(fā)現(xiàn)要產(chǎn)生的立即數(shù)是一個(gè)程序地址,它會(huì)自動(dòng)將LSB

置位,若是數(shù)據(jù)地址,則不會(huì)自動(dòng)置位LSB。

3.NOP偽指令

NOP偽指令是空操作(無操作)指令。指令執(zhí)行后不影響任何寄存器和內(nèi)存單元,只是消耗了CUP的一點(diǎn)時(shí)間。NOP偽指令在匯編后,也會(huì)生成一條類似于MOVR0,R0的指令。

指令格式如下:NOP

NOP多用于軟件延遲,且NOP指令不改變ALU

狀態(tài)標(biāo)志。

3.4ARM匯編程序設(shè)計(jì)基礎(chǔ)

3.4.1ARM匯編指示命令在ARM匯編語言程序里,有一些特殊指令助記符,這些助記符與指令系統(tǒng)的助記符不同,沒有相對(duì)應(yīng)的操作碼,通常將這些特殊指令助記符稱為匯編指示命令,與x86所稱的偽指令相對(duì)應(yīng)。

在ARM的匯編程序中,有如下幾種匯編指示命令:

·符號(hào)定義匯編指示命令。

·數(shù)據(jù)定義匯編指示命令。

·匯編控制匯編指示命令。

·結(jié)構(gòu)描述匯編指示命令。

·報(bào)告匯編指示命令。

·其他匯編指示命令。

1.符號(hào)定義匯編指示命令

符號(hào)定義匯編指示命令用于定義ARM匯編程序的變量,對(duì)變量進(jìn)

行賦值及定義寄存器名稱。該類主要的匯編指示命令如下:

·全局變量聲明:GBLA、GBLL

和GBLS。

·局部變量聲明:LCLA、LCLL

和LCLS。

·變量賦值:SETA、SETLL

和SETS。

·為一個(gè)通用寄存器列表定義名稱:RLIST。

1)GBLA、GBLL和GBLS

GBLA、GBLL和GBLS匯編指示命令用于聲明一個(gè)ARM程序的全局變量,并將其初始化。

GBLA

匯編指示命令用于聲明一個(gè)全局的算術(shù)變量,并將其初始化為0。

GBLL

匯編指示命令用于聲明一個(gè)全局的邏輯變量,并將其初始化為{FALSE}。

GBLS

匯編指示命令用于聲明一個(gè)全局的字符串變量,并將其初始化為空字符串“”。

2)LCLA、LCLL

和LCLS

LCLA、LCLL

和LCLS

匯編指示命令用于聲明一個(gè)ARM程序的局部變量,并將其初始化。

LCLA匯編指示命令用于聲明一個(gè)局部的算術(shù)變量,并將其初始化為0。

LCLL

匯編指示命令用于聲明一個(gè)局部的邏輯變量,并將其初始化為{FALSE}。

LCLS

匯編指示命令用于聲明一個(gè)局部的字符串變量,并將其初始化為空字符串“”。

3)SETA、SETL

和SETS

SETA,SETL

和SETS

匯編指示命令用于給一個(gè)ARM程序中的變量賦值。

SETA

匯編指示命令用于給一個(gè)全局/局部的算術(shù)變量賦值。

SETL

匯編指示命令用于給一個(gè)全局/局部的邏輯變量賦值。

SETS

匯編指示命令用于給一個(gè)全局/局部的字符串變量賦值。

4)RLIST

RLIST

為一個(gè)通用寄存器列表定義名稱。使用該匯編指示命令定義的名稱可在ARM指令LDM/STM中使用。在LDM/STM指令中,列表中的寄存器訪問次序根據(jù)寄存器的編號(hào)由低到高,而與列表中的寄存器排列次序無關(guān)。

2.數(shù)據(jù)定義匯編指示命令

數(shù)據(jù)定義匯編指示命令用于數(shù)據(jù)表定義、文字池定義、數(shù)據(jù)空間分配等。該類匯編指示命令如下:

·聲明一個(gè)文字池:LTORG。

·定義一個(gè)結(jié)構(gòu)化的內(nèi)存表中的首地址:MAP。

·定義結(jié)構(gòu)化內(nèi)存表中的一個(gè)數(shù)據(jù)域:FLELD。

·分配一塊內(nèi)存單元,并用0初始化:SPACE。

·分配一段字節(jié)的內(nèi)存單元,并用指定的數(shù)據(jù)初始化:DCB。

·分配一段字的內(nèi)存單元,并用指定的數(shù)據(jù)初始化:DCD

和DCDU。

·分配一段字的內(nèi)存單元,將每個(gè)單元的內(nèi)容初始化為該單元相對(duì)于靜態(tài)基址寄存器的偏移量:DCDO。

·分配一段字的內(nèi)存單元,并用雙精度的浮點(diǎn)數(shù)據(jù)初始化:DCFD和DCFDU。

·分配一段字的內(nèi)存單元,并用單精度的浮點(diǎn)數(shù)據(jù)初始化:DCFS

和DCFSU。

·分配一段字的內(nèi)存單元,并用單精度的浮點(diǎn)數(shù)據(jù)初始化,指定內(nèi)存單元存放的是代碼,而不是數(shù)據(jù):DCI。

·分配一段雙字的內(nèi)存單元,并用64位的整數(shù)數(shù)據(jù)初始化:DCQ和DCQU。

·分配一段半字的內(nèi)存單元,并用指定的數(shù)據(jù)初始化:DCW和DCWU。

1)LTORG

LTORG

用于聲明一個(gè)文字池,在使用LDR偽指令時(shí),匯編器會(huì)將偽指令中的32位立即數(shù)(或地址)存入文字池。若沒有使用LTORG

聲明文字池,則匯編器會(huì)在程序末尾自動(dòng)聲明。

2)MAP

MAP

用于定義一個(gè)結(jié)構(gòu)化的內(nèi)存表的首地址。此時(shí),內(nèi)存表的位置計(jì)數(shù)器{VAR}設(shè)置為該地址值,{VAR}為匯編器的內(nèi)置變量,“”與MAP

同義。

3)FLELD

FLELD

用于定義結(jié)構(gòu)化內(nèi)存表中的一個(gè)數(shù)據(jù)域?!埃!迸cFLELD

同義。

FLELD匯編指示命令常與MAP

匯編指示命令配合使用,用來定義結(jié)構(gòu)化的內(nèi)存表。MAP

匯編指示命令定義內(nèi)存表的首地址;FLELD

匯編指示命令定義內(nèi)存表中的各個(gè)數(shù)據(jù)域,并可以為每個(gè)數(shù)據(jù)域指定一個(gè)標(biāo)號(hào)供其他的指令引用。

注意,

MAP

和FLELD

匯編指示命令僅用于定義數(shù)據(jù)結(jié)構(gòu),并不實(shí)際分配存儲(chǔ)單元。

4)SPACE

SPACE用于分配一塊內(nèi)存單元,并用0初始化?!埃ァ迸cSPACE同義。

5)DCB

DCB用于分配一段字節(jié)的內(nèi)存單元,并用DCB命令中的expr初始化,一般可用來定義數(shù)據(jù)表格或字符串。“=”與DCB同義。

6)DCD

DCD

用于分配一段字的內(nèi)存單元,并用匯編指示命令中的expr初始化。DCD

匯編指示命令分配的內(nèi)存需要字對(duì)齊,一般可用來定義數(shù)據(jù)表格或其他常數(shù)?!?”與DCD

同義。必要時(shí),匯編程序在定義的第一個(gè)數(shù)字前最多插入3個(gè)填充字節(jié),以實(shí)現(xiàn)4字節(jié)的對(duì)齊。

7)DCI

在ARM代碼中,DCI用于分配一段字節(jié)的內(nèi)存單元,用指定的數(shù)據(jù)expr初始化,指定內(nèi)存單元存放的是代碼,而不是數(shù)據(jù)。

在Thumb代碼中,DCI用于分配一段半字節(jié)的內(nèi)存單元,用指定的數(shù)據(jù)expr初始化,指定內(nèi)存單元存放的是代碼,而不是數(shù)據(jù)。

3.其他常用匯編指示命令

在匯編程序中還有一些其他的匯編指示命令經(jīng)常會(huì)被使用。

·邊界對(duì)齊:ALIGN。

·段定義:AREA。

·匯編結(jié)束:END。

·程序入口:ENTRY。

·常量定義:EQU。

1)ALIGN

ALIGN

匯編指示命令通過添加補(bǔ)丁字節(jié)使當(dāng)前位置滿足一定的對(duì)齊方式。

2)AREA

AAREA匯編指示命令用于定義一個(gè)代碼段或數(shù)據(jù)段。ARM匯編程序設(shè)計(jì)采用分段式設(shè)計(jì),一個(gè)ARM源程序至少需要一個(gè)代碼段,大的程序可以包含多個(gè)代碼段及數(shù)據(jù)段。

3)END

END匯編指示命令用于指示匯編編譯器源文件結(jié)朿。每個(gè)匯編源文件均要使用一個(gè)END匯編指示命令,指示本源程序結(jié)束。

4)ENTRY

ENTRY匯編指示命令用于指定程序的入口點(diǎn)。

5)EQU

EQU匯編指示命令為數(shù)字常量,基于寄存器的值和程序中的標(biāo)號(hào)定義一個(gè)名稱。“?”與EQU同義。它的作用類似于C語言中的#define

用來為一個(gè)常量定義名稱。

3.4.2ARM匯編語句格式

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

在ARM匯編語句中,所有標(biāo)號(hào)必須在一行的頂格寫,而所有指令均不能頂格寫。ARM匯編器對(duì)標(biāo)識(shí)符大小寫敏感,書寫符號(hào)及指令時(shí)字母大小寫要一致。

1.常用符號(hào)

在ARM匯編語句中,符號(hào)可以代表地址、變量和數(shù)字常量。

符號(hào)的命名規(guī)則如下:

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

·除局部標(biāo)號(hào)以數(shù)字開頭外,其他的符號(hào)不能以數(shù)字開頭。

·符號(hào)區(qū)分大小寫,且所有字符都是有意義的。

·符號(hào)在其作用域范圍內(nèi)必須唯一。

·符號(hào)不能與系統(tǒng)內(nèi)部或者系統(tǒng)預(yù)定義的符號(hào)同名。

·符號(hào)不能與助記符、匯編指示命令同名。

1)變量

程序中的變量是指其值在程序的運(yùn)行過程中可以改變的量。ARM(Thumb)匯編程序所支持的變量有數(shù)字變量、邏輯變量和字符串變量。

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

邏輯變量用于在程序的運(yùn)行中保存邏輯值,邏輯值只有兩種取值情況:真或假。

2)數(shù)字常量

3)變量替換

程序中的變量可通過代換操作取得一個(gè)常量。代換操作符為“$

”。

如果在數(shù)字變量前面有一個(gè)代換操作符“$

”,編譯器會(huì)將該數(shù)字變量的值轉(zhuǎn)換為十六進(jìn)制的字符串,并用該十六進(jìn)制的字符串代換“$

”后的數(shù)字變量。

如果在邏輯變量前面有一個(gè)代換操作符“$

”,編譯器會(huì)將該邏輯變量代換為它的取值(真或假)。

如果在字符串變量前面有一個(gè)代換操作符“$

”,編譯器會(huì)將該字符串變量代換為已經(jīng)賦值給它的字符串。

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

標(biāo)號(hào)是表示程序中的指令或者數(shù)據(jù)地址的符號(hào)。標(biāo)號(hào)的生成方式可以有以下三種:

(1)基于PC的標(biāo)號(hào)。基于PC的標(biāo)號(hào)是指位于目標(biāo)指令前的標(biāo)號(hào)或程序中的數(shù)據(jù)定義匯編指示命令前的標(biāo)號(hào)。

(2)基于寄存器的標(biāo)號(hào)。

(3)絕對(duì)地址。

2.表達(dá)式和運(yùn)算符

表達(dá)式是由符號(hào)、數(shù)值、單目或多目操作符以及括號(hào)組成的。在一個(gè)表達(dá)式中,各種元素的優(yōu)先級(jí)如下所示:

·括號(hào)內(nèi)的表達(dá)式優(yōu)先級(jí)最髙。

·各種操作符有一定的優(yōu)先級(jí)。

·相鄰的單目操作符的執(zhí)行順序?yàn)樽杂蚁蜃?,單目操作符?yōu)先級(jí)髙于其他操作符。

·優(yōu)先級(jí)相同的雙目操作符的執(zhí)行順序?yàn)樽宰笙蛴摇?/p>

1)數(shù)字表達(dá)式

數(shù)字表達(dá)式一般由數(shù)字常量、數(shù)字變量、運(yùn)算符和括號(hào)構(gòu)成。

(1)數(shù)字常量。數(shù)字常量分為整數(shù)數(shù)字量和浮點(diǎn)數(shù)字量。浮點(diǎn)數(shù)字量有單精度和雙精度浮點(diǎn)數(shù)之分。

(2)數(shù)字變量。數(shù)字變量用匯編指示命令GBLA或LCLA

聲明,用SETA

賦值,代表32位數(shù)字量。

(3)運(yùn)算符。與數(shù)字表達(dá)式相關(guān)的運(yùn)算符如下:

①“+”、“-”、“×”、“/”及“MOD”算術(shù)運(yùn)算符。

以上的算術(shù)運(yùn)算符分別代表加、減、乘、除和取余數(shù)運(yùn)算。例如,以x和Y表示兩個(gè)數(shù)字表達(dá)式,則:

x+Y表示x與Y的和。

x-Y表示x與Y的差。

x×Y表示x與Y的乘積。

x/Y表示x除以Y的商。

x∶MOD∶Y表示x除以Y的余數(shù)。

②“ROL”、“ROR”、“SHL”及“SHR”移位運(yùn)算符。

以x和Y表示兩個(gè)數(shù)字表達(dá)式,以上移位運(yùn)算符代表的運(yùn)算如下:

x∶ROL∶Y表示將x循環(huán)左移Y位。

x∶ROR∶Y表示將x循環(huán)右移Y位。

x∶SHL∶Y表示將x左移Y位。

x∶SHR∶Y表示將x右移Y位。

③“AND”、“OR”、“NOT”及“EOR”按位邏輯運(yùn)算符。

以x和Y表示兩個(gè)數(shù)字表達(dá)式,以上按位邏輯運(yùn)算符代表的運(yùn)算如下:

x∶AND∶Y表示將x和Y按位作邏輯與的操作。

x∶OR∶Y表示將x和Y按位作邏輯或的操作。

∶NOT∶Y表示將Y按位作邏輯非的操作。

x∶EOR∶Y表示將x和Y按位作邏輯異或的操作。

2)邏輯表達(dá)式

邏輯表達(dá)式由邏輯常量(TRUE

或者FALSE)、邏輯運(yùn)算符、關(guān)系操作符和括號(hào)組成,取值為{FALSE}或{TRUE}。

(1)關(guān)系操作符。

以x和Y表示兩個(gè)邏輯表達(dá)式,以上運(yùn)算符代表的運(yùn)算如下:

x=Y表示x等于Y。

x>Y表示x大于Y。

x<Y表示x小于Y。

x>=Y表示x大于或等于Y。

x<=Y表示x小于或等于Y。

x/=Y表示x不等于Y。

x<>Y表示x不等于Y。

(2)邏輯運(yùn)算符。“LAND”、“LOR”、“LNOT”及“LEOR”運(yùn)算符。

以x和Y表示兩個(gè)邏輯表達(dá)式,以上邏輯運(yùn)算符代表的運(yùn)算如下:

x∶LAND

∶Y表示將x和Y作邏輯與的操作。

x∶LOR

∶Y表示將x和Y作邏輯或的操作。

∶LNOT

∶Y表示將Y作邏輯非的操作。

x∶LEOR∶Y表示將x和Y作邏輯異或的操作。

3)字符串表達(dá)式

字符串表達(dá)式由字符串、字符串常量、運(yùn)算符和括號(hào)組成。字符串的最大長度為512字節(jié),最小長度為0字節(jié)。

(1)字符串。

(2)字符串常量。

(3)運(yùn)算符。

常用的與字符串表達(dá)式相關(guān)的運(yùn)算符如下:

①“LEN”運(yùn)算符。

②“CHR”運(yùn)算符。

③“STR”運(yùn)算符。

④“LEFT”運(yùn)算符。

⑤“Right”運(yùn)算符。

⑥“CC”運(yùn)算符。

4)基于寄存器和PC的表達(dá)式

基于寄存器的表達(dá)式表示某個(gè)寄存器的值加上或減去一個(gè)數(shù)字表達(dá)式。

基于PC的表達(dá)式表示PC寄存器的值加上或減去一個(gè)數(shù)字表達(dá)式?;赑C的表達(dá)式通常由程序中的標(biāo)號(hào)與一個(gè)數(shù)字表達(dá)式組成。

3.4.3ARM匯編語言格式

在ARM(Thumb)匯編語言程序中,以程序段為單位組織代碼。段是相對(duì)獨(dú)立的指令或數(shù)據(jù)序列,具有特定的名稱。段可分為代碼段和數(shù)據(jù)段,代碼段的內(nèi)容為執(zhí)行代碼,數(shù)據(jù)段存放代碼運(yùn)行時(shí)需要用到的數(shù)據(jù)。

可執(zhí)行映像文件通常由以下幾部分構(gòu)成:

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

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

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

鏈接器根據(jù)系統(tǒng)默認(rèn)或用戶設(shè)定的規(guī)則,將各個(gè)段安排在存儲(chǔ)器中的相應(yīng)位置。因此源程序中段之間的相對(duì)位置與可執(zhí)行的映像文件中段的相對(duì)位置一般不會(huì)相同。

3.4.4ARM匯編語言基本結(jié)構(gòu)程序設(shè)計(jì)方法

1.順序結(jié)構(gòu)設(shè)計(jì)方法

順序結(jié)構(gòu)表示程序中的各操作是按照它們出現(xiàn)的先后順序執(zhí)行的,其流程如圖3.7所示。圖3.7順序結(jié)構(gòu)

【例3.1】兩個(gè)32位數(shù)相加,并將結(jié)果儲(chǔ)存到存儲(chǔ)器單元。

解:兩個(gè)32位數(shù)保存在內(nèi)存value1和value2單元。先用偽指令LDR取出第一個(gè)操作數(shù)的地址,再通過間接尋址取出操作數(shù)。以后的操作數(shù)地址都是通過加法(加4)來取得,而不是通過偽指令LDR。這樣的選擇,使指令的執(zhí)行會(huì)更快一些。最后用一條跳轉(zhuǎn)指令結(jié)束程序。使用這段代碼時(shí),可以根據(jù)所使用的匯編環(huán)境再行修改。

【例3.2】查表程序。通過查表來求0~8的階乘。

解:查表程序是一種典型的順序程序。查表可以避免大量的計(jì)算,快捷地得到所需的結(jié)果。一般情況下,通過基址和變址尋址就可以獲得查表的結(jié)果。

·把表格的首地址存入基址寄存器。

·通過查表項(xiàng)得到偏移量,有時(shí)需要簡單計(jì)算。

·通過適當(dāng)?shù)募虞d指令就可以得到查表的結(jié)果。

整個(gè)程序安排了兩個(gè)段:代碼段和數(shù)據(jù)段。數(shù)據(jù)段里是要查的表格,當(dāng)然還有查表項(xiàng)和結(jié)果項(xiàng)。在查表以前,對(duì)查表項(xiàng)要作“乘4”的處理。因?yàn)槊總€(gè)表格項(xiàng)都是32位數(shù)據(jù)(4個(gè)字節(jié)),查表項(xiàng)加1,查表的地址要加4。查表項(xiàng)乘4才是要查表的位置。程序中通過左移兩位來實(shí)現(xiàn)“乘4”。程序中還使用了以R1為第二操作數(shù)的基址變址尋址,執(zhí)行一條指令就得到查表的結(jié)果。程序代碼如下:

2.選擇結(jié)構(gòu)設(shè)計(jì)方法

選擇結(jié)構(gòu)表示程序的處理步驟出現(xiàn)了分支,它需要根據(jù)某一特定的條件選擇其中的一個(gè)分支執(zhí)行。選擇結(jié)構(gòu)有單選擇、雙選擇和多選擇三種形式,如圖3.8所示。圖3.8選擇結(jié)構(gòu)

ARM指令的條件碼可以分為兩類。一類是從標(biāo)志出發(fā),4個(gè)標(biāo)志對(duì)應(yīng)8個(gè)條件;另一類是從數(shù)的比較出發(fā),根據(jù)有符號(hào)數(shù)、無符號(hào)數(shù)的比較有10種情況,對(duì)應(yīng)了10個(gè)條件碼。當(dāng)然,這兩類條件碼有重復(fù)。例如,條件

溫馨提示

  • 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. 人人文庫網(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)論