微機原理 第九章學習資料_第1頁
微機原理 第九章學習資料_第2頁
微機原理 第九章學習資料_第3頁
微機原理 第九章學習資料_第4頁
微機原理 第九章學習資料_第5頁
已閱讀5頁,還剩58頁未讀 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

第九章

ARM程序設(shè)計2025/4/251本章主要內(nèi)容掌握

匯編語言偽指令集和匯編語句格式

ARM程序結(jié)構(gòu) 理解ARM匯編語言與C/C++的混合編程ARM工程特點和程序框架2電子工程學院9.1ARM常用開發(fā)環(huán)境基于Windows平臺ADS,目前已經(jīng)基本被替代RealViewDeveloperSuite(RVDS)EmbeddedWorkbenchforARM(EWARM),IARSystem公司,入門簡單,授權(quán)費用高RealViewMicrocontrollerDevelopmentKit(MDK),Keil公司,多用于低端ARM處理器開發(fā)基于Linux平臺ARM-Linux-GCC,GNU公司,使用繁瑣但不需授權(quán)費用CodeWarriorIDE+RVDebugger3電子工程學院CodeWarriorIDE的主窗口4電子工程學院RVD調(diào)試器主窗口5電子工程學院9.2匯編語言程序設(shè)計特點匯編語言依賴機器硬件,不同CPU提供的匯編指令可能有很大的不同,因此匯編源程序幾乎不具移植性;但匯編語言程序速度快、效率高,更能發(fā)揮機器硬件的長處;2.匯編程序需要用戶將匯編過程中需要的一些輔助信息明確地寫入源程序,如:內(nèi)存邏輯段的劃分情況、數(shù)據(jù)在內(nèi)存中的存放情況,等等。這些信息的說明由匯編程序指定相應(yīng)的偽指令來完成,并不由CPU定義;3.偽指令是在匯編過程中執(zhí)行的,因而不會在機器語言程序中產(chǎn)生目標代碼;只有CPU定義的(助記符)指令才會生成目標代碼,并在程序運行過程中執(zhí)行;匯編語言源程序機器語言程序(目標代碼)匯編(匯編程序)高級語言源程序編譯或解釋(編譯程序)6電子工程學院源程序經(jīng)匯編得到的目標代碼實際上也是不能運行 的,還要經(jīng)過系統(tǒng)的鏈接定位后才能生成真正的 可執(zhí)行文件。

即一般用匯編語言開發(fā)應(yīng)用軟件時應(yīng)依次完成以下幾個步驟:(1)編輯得到源程序(2)匯編得到目標代碼(解決語法錯誤)(3)鏈接得到可執(zhí)行文件(解決定位錯誤)(4)調(diào)試得到功能正確的應(yīng)用軟件(解決邏輯錯誤)(以上第2~4步任何一步有錯都應(yīng)返回到第1步重來)匯編語言、匯編語言源程序、目標程序、可執(zhí)行程序助記符指令、偽指令匯編、匯編器(匯編軟件、匯編程序)7電子工程學院9.2.1符號定義偽指令

符號類型指示符功能

符號定義偽指令GBLA聲明和初始化一個全局算術(shù)變量,初始值為0GBLL聲明和初始化一個全局邏輯變量,初始值為{FALSE}GBLS聲明和初始化一個全局字符串變量,初始值為空LCLA聲明和初始化一個局部算術(shù)變量,初始值為0。局部算術(shù)變量只能在宏中進行聲明。LCLL聲明和初始化一個局部邏輯變量,初始值為{FALSE}。局部邏輯變量只能在宏中進行聲明。LCLS聲明和初始化一個局部字符串變量,初始值為空。局部字符串變量只能在宏中進行聲明。SETA給一個局部或全局算術(shù)變量置值SETL給一個局部或全局邏輯變量置值SETS給一個局部或全局字符串變量置值RLIST給寄存器集命名CN給一個協(xié)處理器寄存器命名CP給一個特定協(xié)處理器命名,協(xié)處理器號為0~15DN給一個雙精度VFP寄存器命名SN給一個單精度VFP寄存器命名FN給一個特定的浮點寄存器命名8電子工程學院定義全局變量GBLATest1 ;聲明全局數(shù)字變量Test1

GBLLTest2 ;聲明全局邏輯變量Test2

GBLSTest3 ;聲明全局字符串變量為Test3

書寫格式:GBLA/GBLL/GBLS

變量名應(yīng)用示例:9電子工程學院定義局部變量書寫格式:LCLA/LCLL/LCLS

變量名LCLAtest4 ;聲明局部數(shù)字變量test4LCLLtest5 ;聲明局部邏輯變量test5LCLStest6 ;聲明局部字符串變量test6應(yīng)用示例:10電子工程學院給變量賦值書寫格式:變量名SETA/SETL/SETS

表達式Test1SETA0xaa

Test2SETL{TRUE}Test3SETS"Testing”

GBLATest1GBLLTest2GBLSTest3應(yīng)用示例:11電子工程學院給通用寄存器列表命名書寫格式:名稱RLIST{list-of-registers}RegListRLIST{R0-R5,R8,R10};聲明寄存器列表RegList,LDM/STM指令可通過該名稱訪問寄存器列表應(yīng)用示例:12電子工程學院9.2.2數(shù)據(jù)定義偽指令

數(shù)據(jù)定義偽指令LTORG指定一個文字池用以保存數(shù)據(jù)^或MAP指定一個內(nèi)存表的首址#或FIELD指定內(nèi)存表中的各數(shù)據(jù)域的長度(一般在MAP之后)%或SPACE指定一塊存儲器的長度并將其中單元初始化為0=或DCB分配一片連續(xù)的字節(jié)單元并初始化分配一片連續(xù)的字節(jié)單元并用于存放代碼&或DCD分配一片連續(xù)的字單元并初始化(字邊界對齊)DCDU分配一片連續(xù)的字單元并初始化(任意邊界)DCDO分配一片連續(xù)的字單元,并初始化為到靜態(tài)基址寄存器R9的偏移量(字邊界對齊)DCFD分配一片連續(xù)的字單元給雙精度浮點數(shù)并初始化(字邊界對齊)分配一片連續(xù)的字單元給單精度浮點數(shù)并初始化(字邊界對齊)DCFDU分配一片連續(xù)的字單元給雙精度浮點數(shù)并初始化(任意邊界)分配一片連續(xù)的字單元給單精度浮點數(shù)并初始化(任意邊界)DCFSDCFSUDCIDCQ分配一片連續(xù)的8字節(jié)單元并初始化(字邊界對齊)DCQU分配一片連續(xù)的8字節(jié)單元并初始化(任意邊界)DCW分配一片連續(xù)的半字單元并初始化(半字邊界對齊)DCWU分配一片連續(xù)的半字單元并初始化(任意邊界)DATA標識代碼段中的數(shù)據(jù)標號,該符號后是DCB等13電子工程學院StrDCB“Thisisatest!” ;分配一片連續(xù)的字節(jié)存儲單元并初始化Test2DataDCW1,2,3 ;分配一片連續(xù)的半字存儲單元并初始化DataTestDCD4,5,6 ;分配一片連續(xù)的字存儲單元并初始化FdataTestDCFD2E115,-5E7 ;分配一片連續(xù)的字存儲單元并初始化FdataTestDCFS2E5,-5E-7;分配一片連續(xù)的字存儲單元并初始化DataTestDCQ100 ;分配一片連續(xù)的8字節(jié)存儲單元并初始化DataSpaceSPACE100 ;分配連續(xù)100個字節(jié)存儲單元并初始化為0

定義一個首址為4096(0x1000)的內(nèi)存表,該表中包含5個字段:A(4Bytes)、B(4Bytes)、X(8Bytes)、Y(8Bytes)、String(256Bytes)。 MAP0x1000 ;內(nèi)存表首地址的值為0x1000A FIELD 4 ;定義A的長度為4字節(jié),位置為0x1000B FIELD 4 ;定義B的長度為4字節(jié),位置為0x1004X FIELD 8 ;定義X的長度為8字節(jié),位置為0x1008Y FIELD 8 ;定義Y的長度為8字節(jié),位置為0x1010String FIELD 256 ;定義String為256字節(jié),位置為0x1018 LDR R6,A 基于絕對地址的內(nèi)存表僅可訪問指令前/后4KB地址范圍的數(shù)據(jù)字段雙精度單精度14電子工程學院定義一個內(nèi)存表,首址為固定地址0與R9的和,表中包含同樣字段。 MAP 0,R9 ;內(nèi)存表首地址為0與R9寄存器內(nèi)容的和A FIELD 4 ;定義A的長度為4字節(jié),相對位置為0B FIELD 4 ;定義B的長度為4字節(jié),相對位置為4X FIELD 8 ;定義X的長度為8字節(jié),相對位置為8Y FIELD 8 ;定義Y的長度為8字節(jié),相對位置為16String FIELD 256 ;定義String為256字節(jié),相對位置為24 ADR R9,DATASTART;偽指令ADR初始化R9 LDR R5,B ;相當于LDRR5,[R9,#4]可訪問地址范圍超過4KB的數(shù)據(jù)基于相對地址的內(nèi)存表定義一個內(nèi)存表,其首址為PC的值,表中包含同樣字段。Dstruc SPACE 280 ;分配280個字節(jié)單元 MAP Dstruc ;內(nèi)存表首地址為DstrucA FIELD 4 ;定義A的長度為4字節(jié),相對位置為0B FIELD 4 ;定義B的長度為4字節(jié),相對位置為4X FIELD 8 ;定義X的長度為8字節(jié),相對位置為8Y FIELD 8 ;定義Y的長度為8字節(jié),相對位置為16String FIELD 256 ;定義String為256字節(jié),相對位置為24 LDR R5,B ;相當于LDRR5,[PC,#4]基于PC的內(nèi)存表可訪問地址范圍不超過4KB的數(shù)據(jù)15電子工程學院匯編控制偽指令

GBLACounter ;聲明全局的數(shù)字變量Counter Counter SETA3 ;由變量Counter控制循環(huán)次數(shù)…… WHILECounter<10

指令序列

修改Counter的值 WEND助記符指令功能描述IF、ELSE和ENDIF根據(jù)條件成立與否決定是否編譯某個指令序列WHILE和WEND根據(jù)條件成立與否決定是否循環(huán)編譯某個指令序列MACRO和MEND將一段代碼用一個標號替代,可在程序中多次調(diào)用該段代碼MEXIT從宏定義中跳轉(zhuǎn)出去16電子工程學院宏和宏定義指令

宏定義以MACRO指示符開始,以MEND結(jié)束,MACRO

$標號宏名 $參數(shù)1,$參數(shù)2,……

宏體MENDMACRO和MEND偽指令可以嵌套使用。

宏的使用方式和功能與子程序有些相似。子程序可以提供模塊化的程序設(shè)計、節(jié)省存儲空間并提高運行速度,但在使用子程序結(jié)構(gòu)時需要保護現(xiàn)場,從而增加了系統(tǒng)的開銷。因此,在代碼較短且需要傳遞的參數(shù)較多時,可以使用宏指令代替子程序。17電子工程學院定義一條宏指令,使其可以完成測試-跳轉(zhuǎn)操作。 MACRO ;宏定義開始 $lable

TestAndBranch$dest,$reg,$cc $lableCMP$reg,#0 B$cc$dest MEND ;宏定義結(jié)束

宏名宏參目標地址測試寄存器條件用于構(gòu)造宏定義體內(nèi)的標號

……testTestAndBranchNonZero,R0,NE

;程序中的宏調(diào)用 …… NonZero ……test CMPR0,#0

;程序匯編時宏展開

BNENonZero …… ;其它指令序列NonZero …… ;其它指令序列18電子工程學院MACRO ;宏定義開始$lable

xmac$p1,$p2 ;宏的名稱為xmac,有兩個參數(shù)$p1和$p2$lable.loop1

;$lable.loop1為宏定義體的內(nèi)部標號

……BGE$lable.loop1$lable.loop2指令 ;$lable.loop2為宏定義體的內(nèi)部標號BL$p1 ;參數(shù)$p1為一個子程序的名稱BGT$lable.loop2 ……

ADR$p2MEND;宏定義結(jié)束

abcxmacsubr1,de ;宏調(diào)用,其中宏標號為abc,參數(shù)為subr1,de…… ;宏展開abc.loop1 ……BGEabc.loop1abc.loop2BLsubr1BGTabc.loop2……ADRde 19電子工程學院類似宏的偽指令ADR[<cond>]<Rd>,<label>將相對于程序或相對于寄存器的地址載入寄存器中……MOVR0,#0x18;給R0賦值用于查表ADRR3,JumpTable

;裝載跳轉(zhuǎn)表的首地址LDRPC,[R3,R0,LSL#2];查表,將查到的地址賦給PCJumpTable……ADRR3JumpTableLDRPC,[R3,R0,LSL#2]xxxJumpTablexxxxxxJumpTable+72xxxPCR3JumpTablexxx20電子工程學院LDR[<cond>][<.W>]<Rd>,<=expr>/<=label_expr>將32位常數(shù)或地址載入寄存器數(shù)值常數(shù)expr取值位于規(guī)定范圍內(nèi)時匯編器將會生成一個MOV或MVN指令否則匯編器會將常數(shù)放入文字池中,并會生成一個相對于程序的LDR指令,該指令可從文字池中讀取此常數(shù)LDR

R3,=0xFF0 ;把立即數(shù)0xFF0賦值給R3LDRR2,=place;把標號place對應(yīng)的地址賦值給R2

21電子工程學院9.2.4其它常用偽指令

其他常用的偽指令

AREAALIGN從一個字邊界開始指示匯編器匯編一段新的代碼或數(shù)據(jù)部分CODE16指示匯編器將隨后的指令作為16位Thumb指令CODE32指示匯編器將隨后的指令作為32位ARM指令END表示源程序的結(jié)束ENTRY指向程序的入口,一個源文件中只能有一個ENTRY*或EQU對一個常量賦予一個符號名EXPORT或GLOBAL說明了由鏈接器在目標和庫文件中使用的符號IMPORT或EXTERN提供匯編器在當前匯編中未曾定義的符號名GET或INCLUDE包含一個文件,在GET處匯編包含的文件INCBIN包含一個未被匯編過的文件KEEP指示匯編器保留符號表中的局部符號NOFP在匯編語言程序中禁止浮點指令REQUIRE指示兩段之間的依賴關(guān)系REQUIRE8指示當前文件請求堆棧為8字節(jié)對準PRESERVE8指示當前文件保持堆棧為8字節(jié)對準RN給特定的寄存器命名ROUT標記局部標號使用范圍的界面22電子工程學院AREA、ENTRY、END偽指令一個匯編源程序至少包含一個段,程序太長時可分為多個段并用AREA標示;一個匯編源程序最多只能有一個(可以沒有)ENTRY標示程序入口;一個完整的匯編源程序中至少應(yīng)有一個用ENTRY標示的入口,如有多個,則程序的真正入口點由連接器指定;一個匯編源程序用END標示源文件結(jié)束。23/5223電子工程學院AREA、ENTRY、END偽指令AREA段名 屬性1,屬性2,……定義代碼段或數(shù)據(jù)段

1.段名若以數(shù)字開頭,則該段名需用“|”括起來,如|1_test|。

2.屬性字段表示該代碼或數(shù)據(jù)的相關(guān)屬性,多個屬性關(guān)鍵字以逗號分隔:CODE:用于定義代碼段。DATA:用于定義數(shù)據(jù)段。READONLY:指定本段為只讀屬性,代碼段默認為READONLY。READWRITE:指定本段為可讀寫屬性,數(shù)據(jù)段默認為READWRITE。ALIGN表達式:表達式取值為0~31。ELF(可執(zhí)行連接文件)的段默認按字對齊。

COMMON:定義一個通用段,各源文件中同名的COMMON段共享同一段存儲單元。AREAInit,CODE,READONLY ;代碼段Init屬性為只讀ENTRY ;指定應(yīng)用程序的入口點

指令序列END

;通知編譯器源程序結(jié)束24/5224電子工程學院ALIGN偽指令ALIGN{表達式{,偏移量}}ALIGN偽指令可通過添加填充字節(jié)的方式,使當前位置滿足一定的對其方式。其中:表達式可能的取值為2的冪(如1,2,4,8和16等)。若未指定表達式則將當前位置對齊到下一個字的位置。若使用偏移量字段,則當前位置的對齊方式為:表達式+偏移量。AREAInit,CODE,READONLY,ALIEN=3;指定后面的指令 ;為8字節(jié)對齊

指令序列END25電子工程學院CODE16、CODE32偽指令

在ARM指令和Thumb指令混合編程的代碼里,該偽指令用于通知編譯器其后的指令序列為16位還是32位。注意它們只能控制編譯方式,并不能切換處理器狀態(tài)。AREAInit,CODE,READONLY……CODE32

;通知編譯器其后為32位的ARM指令LDRR0,=NEXT+1;將跳轉(zhuǎn)地址放入寄存器R0BXR0 ;程序跳轉(zhuǎn),并將處理器切換到Thumb狀態(tài)……CODE16

;通知編譯器其后為16位的Thumb指令NEXTLDRR3,=0x3FF ……END ;程序結(jié)束26電子工程學院EQU偽指令名稱EQU表達式{,類型}用于為程序中的常量和標號等定義一個等效的字符名稱,類似于C語言中的#define。其中EQU可用“*”代替。當表達式為32位的常量時,其數(shù)據(jù)類型可以為CODE16,CODE32或DATA三種類型之一。TestEQU50 ;定義常量Test的值為50AddrEQU0x55,CODE32 ;定義標號Addr的值為0x55,且該處為32位的ARM指令27電子工程學院EXPORT、IMPORT偽指令書寫格式:EXPORT/GLOBAL標號{[WEAK]}EXPORT用于聲明一個全局標號,該標號可在其他文件中引用。[WEAK]選項聲明其他同名標號優(yōu)先于該標號被引用。IMPORT/EXTERN標號{[WEAK]}書寫格式:IMPORT用于通知編譯器當前源文件可能要引用其他源文件中定義的標號。[WEAK]選項表示所有源文件都沒有定義這個標號時,編譯器不會給出錯誤信息,在多數(shù)情況下將該標號置為0。若該標號被B或BL指令引用,則將B或BL指令置為NOP操作。

使用IMPORT則標號一定會被加入到當前源文件的符號表中。28電子工程學院AREAInit1,CODE,READONLYEXPORTMain;源文件1聲明一個可全局引用的標號Main ……END AREAInit2,CODE,READONLYIMPORTMain;源文件2需要引用在別處定義的標號Main ……END 使用EXTERN則標號未被引用時不會被加入到當前源文件的符號表中。標號在程序中區(qū)分大小寫29電子工程學院INCLUDE(或GET)、INCBIN偽指令I(lǐng)NCLUDE文件名INCBIN文件名INCLUDE(或GET)偽指令用于將一個源文件包含到當前的源文件中。被包含的源文件在當前位置進行匯編處理。INCBIN偽指令用于將一個目標文件或數(shù)據(jù)文件包含到當前的源文件中

被包含的文件不作任何變動,編譯器從其后開始繼續(xù)處理。

AREAInit,CODE,READONLYGETC:\a2.s ;通知編譯器此處插入源文件C:\a2.sINCBINa1.dat ;通知編譯器此處插入數(shù)據(jù)文件a1.datINCBINC:\a2.o ;通知編譯器此處插入目標文件C:\a2.o ……END

編寫匯編源程序時,常將一個源文件專門用于定義宏指令(MACRO)、符號常量(EQU),結(jié)構(gòu)化數(shù)據(jù)類型(MAP和FIELD),再用GET偽指令將這個源文件包含到其他源文件中。30電子工程學院9.2.5匯編語言中常用的符號

在匯編語言程序設(shè)計中,經(jīng)常使用各種符號代替地址、變量和常量等,以增加程序的可讀性。盡管符號的命名由編程者決定,但并不是任意的,必須遵循以下的約定:符號區(qū)分大小寫,同名的大小寫字母符號會被編譯器認為是兩個不同的符號;局部標號可以以數(shù)字開頭,其他標號均不得以數(shù)字開頭;符號在其作用范圍內(nèi)必須唯一;自定義的符號名不能與系統(tǒng)的保留字相同,如指令或偽指令;31電子工程學院常量指其值在程序的運行過程中不能被改變的量ARM(Thumb)匯編程序所支持的常量有數(shù)字常量、邏輯常量和字符串常量。數(shù)字常量一般為32位的整數(shù),用“#”標識。當作為無符號數(shù)時,其取值范圍為0~232-1當作為有符號數(shù)時,其取值范圍為-231~231-1邏輯常量只有兩種取值情況:真{TURE}或假{FAUSE}。字符串常量為一個固定的字符串,一般用于程序運行時的信息提示。32電子工程學院變量

ARM(Thumb)匯編程序支持數(shù)字、邏輯和字符串變量。可用GBLA,GBLL和GBLS偽指令聲明全局變量,用LCLA,LCLL和LCLS偽指令聲明局部變量,并可使用SETA,SETL和SETS對其進行初始化。變量可通過代換操作(“$”)獲得一個常量:數(shù)字變量前加“$”,編譯器會將其值轉(zhuǎn)換為十六進制的字符串,并用該十六進制的字符串代換“$”后的數(shù)字變量。邏輯變量前加“$”,編譯器會將該邏輯變量代換為其值(真或假)。字符串變量前加“$”,編譯器會用其值代換

“$”后的字符串變量。

LCLS S1 ;定義局部字符串變量S1和S2 LCLS S2 S1 SETS "Test!" S2 SETS "Thisisa$S1" ;S2的值為"ThisisaTest!”33電子工程學院算術(shù)/邏輯表達式及運算符由數(shù)字/邏輯變量、數(shù)字/邏輯常量、運算符和括號構(gòu)成。X+Y和X-Y差X×Y乘X/Y除X:MOD:Y余X:ROL:YX循環(huán)左移Y位X:ROR:YX循環(huán)右移Y位X:SHL:YX左移Y位X:SHR:YX右移Y位X:AND:Y按位邏輯與X:OR:Y按位邏輯或:NOT:Y按位邏輯非X:EOR:Y按位邏輯異或算術(shù)運算符移位運算符按位邏輯運算符構(gòu)成數(shù)字表達式(操作數(shù)和運算結(jié)果為數(shù)字型)的運算符34電子工程學院算術(shù)/邏輯表達式及運算符X=YX等于YX>YX大于YX<YX小于YX>=YX大于等于YX<=YX小于等于YX/=YX不等于YX<>YX不等于YX:LAND:Y邏輯與X:LOR:Y邏輯或:LNOT:Y邏輯非X:LEOR:Y邏輯異或邏輯運算符邏輯運算符(操作數(shù)為邏輯型)構(gòu)成邏輯表達式(運算結(jié)果為邏輯常量)的運算符35電子工程學院算術(shù)/邏輯表達式及運算符運算次序的規(guī)定:優(yōu)先級相同的雙目運算符的運算順序為從左到右;相鄰的單目運算符的運算順序為從右到左,且單目運算符的優(yōu)先級高于其他運算符;括號運算符的優(yōu)先級最高。注意:這些運算符構(gòu)成的表達式在匯編過程中進行計算,機器碼中出現(xiàn)的是表達式的值。36電子工程學院字符串表達式及運算符

字符串表達式一般由字符串常量、字符串變量、運算符和括號構(gòu)成。編譯器支持的字符串最大長度為512字節(jié)。

LEN:X

返回字符串X的長度(字符數(shù))。

CHR:M

將0~255之間的整數(shù)M轉(zhuǎn)換為一個字符。STR:X

將數(shù)字或邏輯表達式X轉(zhuǎn)換為一個字符串。對于數(shù)字表達式,STR運算得到一個以十六進制字符組成的字符串;對于邏輯表達式,STR運算得到字符串“T”或“F”。

X:LEFT:Y返回字符串X左端的子串。整數(shù)Y表示要返回的字符個數(shù)。

X:RIGHT:Y

返回字符串X右端的子串。整數(shù)Y表示要返回的字符個數(shù)

X:CC:Y將字符串Y連接到字符串X的后面形成一個新字符串37電子工程學院其它常用運算符?X返回定義符號X的代碼行所生成的可執(zhí)行代碼的長度(字節(jié)數(shù)):DEF:X

判斷是否定義了符號X:如果符號X已經(jīng)定義則結(jié)果為真,否則為假。

BASE:X

返回基于寄存器的表達式X中寄存器的編號。

INDEX:X

返回基于寄存器的表達式X中相對于其基址寄存器的偏移量。38電子工程學院9.3ARM匯編語言程序結(jié)構(gòu)

ARM(Thumb)匯編語言程序中,以程序段(代碼段和數(shù)據(jù)段)為單位組織代碼。一個匯編程序至少應(yīng)該有一個代碼段。當程序較長時,可以分割為多個代碼段和數(shù)據(jù)段,多個段在程序編譯連接時最終形成一個可執(zhí)行的映象文件。可執(zhí)行映象文件通常由以下幾部分構(gòu)成:一個或多個代碼段,代碼段的屬性默認為READONLY。

零個或多個包含初始化數(shù)據(jù)的數(shù)據(jù)段,數(shù)據(jù)段的屬性默認為 READWRITE。

零個或多個不包含初始化數(shù)據(jù)的數(shù)據(jù)段,數(shù)據(jù)段的屬性為默認

為READWRITE。39電子工程學院ARM匯編語言程序段結(jié)構(gòu)GEToption.s

GETaddr.s ……AREA Init,CODE,READONLY

ENTRY

LDR R0,=0x0F

MUL R1,R0,R0

……ENDAREA Data1,DATA,READWRITE

num DCD 10

……END 引用其它源文件代碼段數(shù)據(jù)段40電子工程學院ARM(Thumb)匯編語句格式{標號} {指令或偽指令} {;注釋}助記符可以全部用大寫字母或全部用小寫字母,但不允許在一條指令中大小寫字母混用。如果一條語句太長,可將該長語句分為若干行來書寫,在行的末尾用“\”表示下一行與本行為同一條語句。指令中可以出現(xiàn)常量、變量及表達式。41電子工程學院AREAInit,CODE,READONLYENTRYSTARTLDRR0,=0x3FF5000LDRR1,0xFFSTRR1,[R0]LDRR0,=0x3FF5008LDRR1,0x01STRR1,[R0]…ENDAREA偽指令定義一個段,并說明段的相關(guān)屬性ENTRY偽指令標識程序的入口點每一個匯編源文件都必須有一條END偽指令,指示匯編的結(jié)束偽指令LDR對于不能被MOV和MVN指令所讀取的立即數(shù),將其變成常量進行讀取。存儲單元地址標號START代表第一條指令的存放地址42電子工程學院AREABlock,CODE,READONLYnumEQU20 ;設(shè)置將要復制的字數(shù)ENTRY StartLDRR0,=src ;R0指向源數(shù)據(jù)區(qū)srcLDRR1,=dst ;R1指向目標數(shù)據(jù)區(qū)dstMOVR2,#num ;R2保存將要復制的字數(shù)MOVSP,#0x400 ;設(shè)置堆棧指針(R13)BlockcopyMOVSR3,R2,LSR#3;需要進行的以8個字為單位的復制次數(shù)BEQCopywords;對于剩下不足8個字的數(shù)據(jù),跳轉(zhuǎn)到CopywordsSTMFDSP!,{R4-R11};將工作寄存器R4-R11壓入堆棧保存OctcopyLDMIAR0!,{R4-R11};從源數(shù)據(jù)區(qū)讀取8個字的數(shù)據(jù),放入8個寄存器中STMIAR1!,{R4-R11};將8個寄存器中的數(shù)據(jù)寫入目標數(shù)據(jù)區(qū)中SUBSR3,R3,#1;將塊復制次數(shù)減1BNEOctcopy;循環(huán)操作,直到完成以8個字為單位的塊復制LDMFDSP!,{R4-R11};從堆棧彈出恢復工作寄存器R4-R11實例一:數(shù)據(jù)塊復制43電子工程學院CopywordsANDSR2,R2,#7;剩下不足8個字的數(shù)據(jù)的字數(shù)BEQStop;如果剩下數(shù)據(jù)的字數(shù)為0,則數(shù)據(jù)復制完成Wordcopy

LDRR3,[R0],#4;從源數(shù)據(jù)區(qū)讀取1個字的數(shù)據(jù),放到R3寄存器中STRR3,[R1],#4;將R3寄存器中的數(shù)據(jù)寫入目標數(shù)據(jù)區(qū)中SUBSR2,R2,#1;將字數(shù)減1BNEWordcopy;循環(huán)操作,直到完成以字為單位的數(shù)據(jù)復制StopMOVR0,#0x18;LDRR1,=0x20026;SWI0x123456;從應(yīng)用程序中退出AREABlockData,DATA,READWRITE ;定義數(shù)據(jù)區(qū)BlockDatasrcDCD1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7;定義源數(shù)據(jù)區(qū)srcdstDCD0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0;定義目標數(shù)據(jù)區(qū)dstEND;結(jié)束匯編44電子工程學院;文件名:TEST1.S;功能:實現(xiàn)兩個寄存器相加;說明:使用ARMulate軟件仿真調(diào)試 AREA Example1,CODE,READONLY;聲明代碼段Example1 ENTRY ;標識程序入口 CODE32 ;聲明32位ARM指令STARTMOV R0,#0 ;設(shè)置參數(shù)

MOV R1,#10LOOP BL ADD_SUB ;調(diào)用子程序ADD_SUB B LOOP ;循環(huán)ADD_SUB ADDS R0,R0,R1 ;R0=R0+R1 MOV PC,LR ;子程序返回 END ;文件結(jié)束使用“;”進行注釋標號頂格主程序子程序45電子工程學院9.4ARM工程中的文件一個ARM工程(project)應(yīng)該由多個文件組成:擴展名為.s的匯編語言源文件擴展名為.c的C語言源文件擴展名為.cpp的C++源文件以及擴展名為.h的頭文件等46電子工程學院ARM匯編與C/C++的混合編程1.初始化程序部分硬件系統(tǒng)的初始化,包括設(shè)定CPU工作狀態(tài),中斷使能,主頻設(shè)定,以及RAM的控制參數(shù)設(shè)置及初始化等,通常都使用匯編代碼。2.初始化部分與主應(yīng)用程序部分的銜接當所有的系統(tǒng)初始化工作完成之后,就需要把程序流程轉(zhuǎn)入到應(yīng)用程序。最簡單的方法是,在匯編語言程序末尾使用跳轉(zhuǎn)指令B或BL直接從啟動代碼轉(zhuǎn)移到C/C++程序入口。3.主應(yīng)用程序的混合編程方式

匯編程序和C/C++程序之間的相互調(diào)用(ATPCS)在C/C++代碼中嵌入?yún)R編指令47電子工程學院基于ARM/Thumb指令集過程調(diào)用的規(guī)則ATPCSPCS用于保證使用不同編程語言的子程序可以分開編寫、編譯,并成功連接,所以它實際上定義了一套有關(guān)過程(函數(shù))調(diào)用者與被調(diào)用者之間的協(xié)議。PCS的制訂是一系列指標的折衷(tradeoff),如生成代碼的大小,調(diào)試功能的支持,函數(shù)調(diào)用上下文處理速度以及內(nèi)存消耗。ARM基本的ATPCS規(guī)定了寄存器使用、數(shù)據(jù)棧使用以及參數(shù)傳遞這三方面的基本規(guī)則;而派生的其他幾種特定的ATPCS則是在此基礎(chǔ)上再添加其他規(guī)則(如支持子程序可重入性、數(shù)據(jù)棧界限檢查等)而形成的。

在基于ARM的混合編程技術(shù)中,C語言子程序只需開發(fā)者指定ATPCS類型,而匯編子程序則需完全依靠開發(fā)者來保證。

48電子工程學院基本ATPCS(1):寄存器使用規(guī)則①寄存器R0~R3(A1~A4)用做子程序參數(shù)傳遞。被調(diào)用的子程序在返回前無需恢復其內(nèi)容。②寄存器R4~R11(V1~V8)用做子程序內(nèi)的局部變量保存。如有使用則應(yīng)進行保護和恢復。(Thumb程序通常只能使用R4~R7)③寄存器R12(IP)用作臨時(scratch)指針。④寄存器R13用作數(shù)據(jù)棧指針SP,不能用于其他用途。SP在子程序進入和退出時的值必須相等。⑤寄存器R14用作連接寄存器LR。如果子程序中保存了返回地址,則R14可用于其他用途。⑥寄存器R15是程序計數(shù)器PC,不能用于其他用途。49電子工程學院ATPCS中的寄存器使用規(guī)則寄存器別名用法R0~R3A1~A4入口參數(shù)/返回值/臨時(scratch)寄存器R4~R11V1~V8子程序局部變量寄存器,其中:R7/V4也作為Thumb狀態(tài)工作寄存器WR;R9/V6在支持可讀寫段位置無關(guān)的ATPCS中用作靜態(tài)基址寄存器SB;R10/V7/在支持數(shù)據(jù)棧檢查的ATPCS中為數(shù)據(jù)棧限制指針SLR11/V8/在支持數(shù)據(jù)棧檢查的ATPCS中為數(shù)據(jù)幀指針FP;R12IP臨時(scratch)寄存器R13SP堆棧指針,不能用于其他用途R14LR連接寄存器R15PC程序計數(shù)器,不能用于其他用途50電子工程學院基本ATPCS(2):數(shù)據(jù)棧使用規(guī)則ARM的數(shù)據(jù)棧可為FD(FullDescending),ED(EmptyDescending),F(xiàn)A(FullAscending)或EA(EmptyAscending),但ATPCS規(guī)定數(shù)據(jù)棧為FD類型,且8字節(jié)對齊的。數(shù)據(jù)棧指針(stackpointer)指向最后入棧的數(shù)據(jù)單元地址。數(shù)據(jù)棧基址(stackbase)指向數(shù)據(jù)棧的最高地址。數(shù)據(jù)棧界限(stacklimit)指向數(shù)據(jù)棧的最低地址。已占用的數(shù)據(jù)棧(usedstack)指棧基址和SP之間的區(qū)域,其中包括棧指針對應(yīng)的內(nèi)存單元。數(shù)據(jù)棧中的數(shù)據(jù)幀(stackframe)指棧中為子程序分配的用來保存寄存器和局部變量的區(qū)域。

對于匯編代碼來說,必須保證在進入該匯編代碼后,直到調(diào)用外部代碼之間,棧指針變化為偶數(shù)個字;應(yīng)使用PRESERVE8偽指令告訴連接器,本匯編代碼是8字節(jié)對齊的;

應(yīng)使用FRAME偽指令描述數(shù)據(jù)幀;51電子工程學院基本ATPCS(3):參數(shù)傳遞規(guī)則1、子程序入口參數(shù)傳遞規(guī)則參數(shù)不超過4個時使用寄存器R0~R3,依次將各字數(shù)據(jù)傳送到寄存器;參數(shù)超過4個時將剩余的字數(shù)據(jù)傳送到數(shù)據(jù)棧,入棧的順序與參數(shù)順序相反,即最后一個參數(shù)先入棧。

2、子程序結(jié)果返回規(guī)則當結(jié)果為一個32位的整數(shù)時通過寄存器R0返回子程序結(jié)果;當結(jié)果為一個64位的整數(shù)時通過R0和R1返回子程序結(jié)果,以此類推;當對于位數(shù)更多的子程序結(jié)果,需要通過調(diào)用內(nèi)存來傳遞。

52電子工程學院C程序調(diào)用匯編函數(shù)匯編程序的設(shè)置要遵循ATPCS規(guī)則,保證程序調(diào)用時參數(shù)、寄存器和堆棧的正確使用。在匯編程序中使用EXPORT

偽指令聲明本子程序,使其它程序可以調(diào)用此子程序。在C語言程序中使用extern關(guān)鍵字聲明要調(diào)用的匯編子程序為外部函數(shù)。匯編程序調(diào)用C函數(shù)匯編程序的設(shè)置要遵循ATPCS規(guī)則,保證程序調(diào)用時參數(shù)、寄存器和堆棧的正確使用。在匯編程序中使用IMPORT偽指令聲明將要調(diào)用的C程序函數(shù)。在正確設(shè)置入口參數(shù)后使用BL調(diào)用C程序函數(shù)。53電子工程學院AREASCopy,CODE,READONLYEXPORTstrcopy ;聲明strcopy為導出符號strcopy

LDRBR2,[R1],#1 ;R1中的值為源數(shù)據(jù)塊的首地址STRBR2,[R0],#1 ;R0中的值為目標數(shù)據(jù)塊的首地址CMPR2,#0BNEstrcopy ;未復制完,循環(huán)繼續(xù)復制MOVPC,LR ;復制完畢,返回ENDexternvoidstrcopy(char*d,constchar*s)

//參數(shù)由左向右依次傳遞給R0~R3:d為目標指針(R0);s為源指針(R1)int

main(void) { constchar*srcstr="Firststring-soure"; chardststr[]="Secondstring-destination"; ……

strcopy(dest,src);//調(diào)用匯編函數(shù)strcopy

…… }數(shù)據(jù)塊復制54電子工程學院例9.7在RVDS上的運行結(jié)果55電子工程學院在匯編函數(shù)f中調(diào)用C函數(shù)g(),以實現(xiàn)下面的功能:intf(inti){return-g(i,2*i,3*i,4*i,5*i)}EXPORTfAREAf,CODE,READONLYIMPORTg ;聲明g為外部引用符號STRLR,[SP,#-4]] ;將斷點存入堆棧ADDR1,R0,R0 ;(R1)=i*2ADDR2,R1,R0 ;(R2)=i*3ADDR3,R1,R2 ;(R3)=i*5STRR3,[SP,#-4]] ;將(R3)即第5個參數(shù)i*5存入堆棧ADDR3,R1,R1 ;(R3)=i*4

BLg ;調(diào)用C函數(shù)g(),返回值在R0中ADDSP,SP,#4 ;調(diào)整數(shù)據(jù)棧指針,

溫馨提示

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

評論

0/150

提交評論