ARM匯編語言程序設計基礎_第1頁
ARM匯編語言程序設計基礎_第2頁
ARM匯編語言程序設計基礎_第3頁
ARM匯編語言程序設計基礎_第4頁
ARM匯編語言程序設計基礎_第5頁
已閱讀5頁,還剩85頁未讀 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

嵌入式系統(tǒng)第9章ARM匯編語言程序設計基礎

匯編偽操作及程序結構基于Linux的GNU匯編器格式匯編語言與C語言混合編程1ARM匯編偽操作及程序結構2匯編語言程序的結構CODE32AREAcodesec,CODE,READONLYmainPROCSTMFDSP!,{LR}ADR R0,strhelloBL_printfBLwelcomefunLDMFDSP!,{LR}strhello;32位ARM指令段代碼段屬性只讀;函數(shù)main;相關寄存器入棧;strhello地址;調(diào)用庫函數(shù);調(diào)用子函數(shù)welcomefun;相關寄存器出棧DCB“Helloworld!\n\0”;定義14字節(jié)的字節(jié)空間ENDP;mainPROC結束welcomefunSTMFDSP!,{LR};子函數(shù)welcomefun;相關寄存器入棧ADR R0,adrstrarm;adrstrarm的地址LDR R0,[R0,#0];strarm的值存入r0BL_printf;調(diào)用庫函數(shù)LDMFDSP!,{LR};相關寄存器出棧adrstrarmDCDstrarm;保存strarm的地址AREAconstdatasec,DATA,READONLY,ALIGN=0strarmDCB“WelcometoARMworld!\n\0”;存放字符串EXPORTmain;全局聲明main,供外部調(diào)用...END;程序結束數(shù)據(jù)段指定數(shù)據(jù)段單字節(jié)對齊偽代碼3ARM匯編程序中每一行的通用格式為:{標號}指令|偽操作|偽指令操作數(shù){;注解}。在ARM匯編語言源程序中,除了標號和注釋外,指令、偽指令和指示符都必須有前導空格,而不能頂格書寫。如果每一行的代碼太長,可以使用字符“\”將其分行書寫,并允許有空行。指令、偽操作和寄存器名既可以用大寫字母,也可以用小寫字母,但不能混用。注釋從“;”開始,到該行結束為止。

標號代表一個地址,段內(nèi)標號的地址值在匯編時確定,段外標號的地址值在鏈接時確定。ARM匯編程序設計4ARM匯編語句格式;R0=0x11234565ARM匯編語句格式;標號start沒有頂格寫;標號后不允許帶:;命令不允許頂格書寫;指令中大小寫不可混合;標號Loop不存在START MOV R0,#1ABC MOV R1,#2 MOV R2,#3LOOP MOV R2,#3 B LOOP6偽操作、宏指令及偽指令的概念偽操作是ARM匯編語言程序里的一些特殊指令助記符,主要是為完成匯編程序做各種準備工作,在源程序進行匯編時由匯編程序處理,而不是在處理器運行期間由機器執(zhí)行。宏指令是一段獨立的程序代碼,它通過偽操作來定義。通過宏名來調(diào)用宏,并可以設置相應的參數(shù)。宏定義本身不會產(chǎn)生代碼,只是在調(diào)用它時把宏體插入到源程序中。偽指令也是ARM匯編語言程序里的特殊指令助記符,也不在處理器運行期間由機器執(zhí)行,它們在匯編時將被合適的機器指令代替成ARM或Thumb指令從而實現(xiàn)真正指令操作。7偽操作符號定義(SymbolDefinition)

偽操作內(nèi)存分配(數(shù)據(jù)定義)(DataDefinition)

偽操作匯編控制(AssemblyControl)

偽操作其他

(Miscellaneous)

偽操作

81、符號定義偽操作偽操作語法格式作用GBLAGBLAVariable聲明一個全局的算術“偽變量”,并將其初始化成0。GBLLGBLLVariable聲明一個全局的邏輯變量,并將其初始化成{FALSE}。GBLSGBLSVariable聲明一個全局的字符串變量,并將其初始化成空串“”。LCLALCLAVariable聲明一個局部的算術變量,并將其初始化成0。LCLLLCLLVariable聲明一個局部的邏輯變量,并將其初始化成{FALSE}。LCLSLCLSVariable聲明一個局部的串變量,并將其初始化成空串“”。SETASETAVariableexpr給一個全局或局部算術變量賦值。SETLSETLVariableexpr給一個全局或局部邏輯變量賦值。SETSSETSVariableexpr給一個全局或局部字符串變量賦值。RLISTnameLIST{listofregisters}為一個通用寄存器列表定義名稱。CNnameCNexpr為一個協(xié)處理器的寄存器定義名稱。CPnameCPexpr為一個協(xié)處理器定義名稱。DN/SNnameDN/SNexprDN/SN為一個雙精度/單精度的VFP寄存器定義名稱。FNnameFNexpr為一個FPA浮點寄存器定義名稱。91、符號定義偽操作偽操作語法格式作用GBLAGBLAVariable聲明一個全局的算術“偽變量”,并將其初始化成0。GBLLGBLLVariable聲明一個全局的邏輯變量,并將其初始化成{FALSE}。GBLSGBLSVariable聲明一個全局的字符串變量,并將其初始化成空串“”。LCLALCLAVariable聲明一個局部的算術變量,并將其初始化成0。LCLLLCLLVariable聲明一個局部的邏輯變量,并將其初始化成{FALSE}。LCLSLCLSVariable聲明一個局部的串變量,并將其初始化成空串“”。SETASETAVariableexpr給一個全局或局部算術變量賦值。SETLSETLVariableexpr給一個全局或局部邏輯變量賦值。SETSSETSVariableexpr給一個全局或局部字符串變量賦值。RLISTnameLIST{listofregisters}為一個通用寄存器列表定義名稱。CNnameCNexpr為一個協(xié)處理器的寄存器定義名稱。CPnameCPexpr為一個協(xié)處理器定義名稱。DN/SNnameDN/SNexprDN/SN為一個雙精度/單精度的VFP寄存器定義名稱。FNnameFNexpr為一個FPA浮點寄存器定義名稱。10符號定義偽操作舉例 GBLA arithmetic ;定義變量arithmitic SETA 0xEF ;賦值;arithmitic EQU 0xEF GBLL logicallogical SETL {TRUE} ;{} GBLS stringstring SETS “haha” ;””成對出現(xiàn):定義+賦值11符號定義偽操作舉例 LCLA arithmeticarithmiticSETA 0xEF LCLL logicallogical SETL {TRUE} LCLS stringstring SETS “haha”12程序中的變量代換程序中的變量可通過代換操作取得一個常量。代換操作符為“$”。

如果在數(shù)字變量前面有一個代換操作符“$”,編譯器會將該數(shù)字變量的值轉換為十六進制的字符串,并將該十六進制的字符串代換“$”后的數(shù)字變量。如果在邏輯變量前面有一個代換操作符“$”,編譯器會將該邏輯變量代換為它的取值(真或假)。如果在字符串變量前面有一個代換操作符“$”,編譯器會將該字符串變量的值代換“$”后的字符串變量。LCLSS1;定義局部字符串變量S1和S2LCLSS2S1SETS“Test!”S2SETS“Thisisa$S1”

;字符串變量S2的值為“ThisisaTest!”

13偽操作符號定義(SymbolDefinition)

偽操作內(nèi)存分配(數(shù)據(jù)定義)(DataDefinition)

偽操作匯編控制(AssemblyControl)

偽操作其他

(Miscellaneous)

偽操作

142、數(shù)據(jù)定義偽操作-列表偽操作語法格式作用LTORGLTORG聲明一個數(shù)據(jù)緩沖池(也稱為文字池)的開始。MAPMAPexpr{,base-register}定義一個結構化的內(nèi)存表的首地址=expr{+BR}FIELD{label}FIELDexpr定義一個結構化內(nèi)存表中的數(shù)據(jù)域長度expr(B)。SPACE{label}SPACEexpr分配一塊連續(xù)內(nèi)存單元expr(B),并用0初始化。DCB{label}DCBexpr{,expr}分配一段字節(jié)內(nèi)存單元,并用expr初始化。DCD/DCDU{label}DCDexpr{,expr}…分配一段字內(nèi)存單元。DCDO{label}DCDOexpr{,expr}…分配一段字對齊的字內(nèi)存單元。DCFD/DCFDU{label}DCFD{U}fpliteral{,fpliteral}…為雙精度的浮點數(shù)分配字對齊的內(nèi)存單元。DCFS/DCFSU{label}DCFS{U}fpliteral{,fpliteral}…為單精度的浮點數(shù)分配字對齊的內(nèi)存單元。DCI{label}DCIexpr{,expr}…在ARM代碼中分配一段字對齊的內(nèi)存單元;在Thumb代碼中,分配一段半字對齊的半字內(nèi)存單元。DCQ/DCQU{label}DCQ{U}{﹣}literal{,{﹣}literal}…分配一段以雙字(8個字節(jié))為單位的內(nèi)存DCW/DCWU{label}DCW{U}expr{,expr}…DCW用于分配一段半字對齊的半字內(nèi)存單元。152、數(shù)據(jù)定義偽操作-列表偽操作語法格式作用LTORGLTORG聲明一個數(shù)據(jù)緩沖池(也稱為文字池)的開始。MAPMAPexpr{,base-register}定義一個結構化的內(nèi)存表的首地址=expr{+BR}FIELD{label}FIELDexpr定義一個結構化內(nèi)存表中的數(shù)據(jù)域長度expr(B)。SPACE{label}SPACEexpr分配一塊連續(xù)內(nèi)存單元expr(B),并用0初始化。DCB{label}DCBexpr{,expr}分配一段字節(jié)內(nèi)存單元,并用expr初始化。DCD/DCDU{label}DCDexpr{,expr}…分配一段字內(nèi)存單元。DCDO{label}DCDOexpr{,expr}…分配一段字對齊的字內(nèi)存單元。DCFD/DCFDU{label}DCFD{U}fpliteral{,fpliteral}…為雙精度的浮點數(shù)分配字對齊的內(nèi)存單元。DCFS/DCFSU{label}DCFS{U}fpliteral{,fpliteral}…為單精度的浮點數(shù)分配字對齊的內(nèi)存單元。DCI{label}DCIexpr{,expr}…在ARM代碼中分配一段字對齊的內(nèi)存單元;在Thumb代碼中,分配一段半字對齊的半字內(nèi)存單元。DCQ/DCQU{label}DCQ{U}{﹣}literal{,{﹣}literal}…分配一段以雙字(8個字節(jié))為單位的內(nèi)存DCW/DCWU{label}DCW{U}expr{,expr}…DCW用于分配一段半字對齊的半字內(nèi)存單元。16數(shù)據(jù)定義偽操作-數(shù)據(jù)緩沖池 AREAExample,CODE,READONLYStart BLfunc1…func1 LDR R1,=0X8888 MOV PC,LR LTORG ;數(shù)據(jù)緩沖池

LTORG語法格式LTORG ;聲明一個數(shù)據(jù)緩沖池(也稱為文字池)的開始。LTORG 偽操作通常放在無條件跳轉指令之后,或者子程序返回指令之后,這樣處理器就不會錯誤地將數(shù)據(jù)緩沖池中的數(shù)據(jù)當作指令來執(zhí)行。172、數(shù)據(jù)定義偽操作-列表偽操作語法格式作用LTORGLTORG聲明一個數(shù)據(jù)緩沖池(也稱為文字池)的開始。MAPMAPexpr{,base-register}定義一個結構化的內(nèi)存表的首地址=expr{+BR}FIELD{label}FIELDexpr定義一個結構化內(nèi)存表中的數(shù)據(jù)域長度expr(B)。SPACE{label}SPACEexpr分配一塊連續(xù)內(nèi)存單元expr(B),并用0初始化。DCB{label}DCBexpr{,expr}分配一段字節(jié)內(nèi)存單元,并用expr初始化。DCD/DCDU{label}DCDexpr{,expr}…分配一段字內(nèi)存單元。DCDO{label}DCDOexpr{,expr}…分配一段字對齊的字內(nèi)存單元。DCFD/DCFDU{label}DCFD{U}fpliteral{,fpliteral}…為雙精度的浮點數(shù)分配字對齊的內(nèi)存單元。DCFS/DCFSU{label}DCFS{U}fpliteral{,fpliteral}…為單精度的浮點數(shù)分配字對齊的內(nèi)存單元。DCI{label}DCIexpr{,expr}…在ARM代碼中分配一段字對齊的內(nèi)存單元;在Thumb代碼中,分配一段半字對齊的半字內(nèi)存單元。DCQ/DCQU{label}DCQ{U}{﹣}literal{,{﹣}literal}…分配一段以雙字(8個字節(jié))為單位的內(nèi)存DCW/DCWU{label}DCW{U}expr{,expr}…DCW用于分配一段半字對齊的半字內(nèi)存單元。182、數(shù)據(jù)定義偽操作-數(shù)據(jù)內(nèi)存表 MAP 8192constaFIELD4 MAP 0,R9x FIELD8y FIELD8 MAP Datastring FIELD16

MAP、FIELD

語法格式

MAPexpr{,base-register};定義一個結構化的內(nèi)存表的首地址=expr{+base-register}{label}FIELDexpr;定義一個結構化內(nèi)存表的數(shù)據(jù)域長度為expr

字節(jié)。192、數(shù)據(jù)定義偽操作-數(shù)據(jù)內(nèi)存表 MAP 8192 consta FIELD4 constb FIELD4 x FIELD8 y FIELD8 string FIELD16使用: LDR R0,consta;LDRR0,[8192]

MAP、FIELD基于絕對地址的內(nèi)存表舉例只能訪問LDR指令前后4KB地址范圍之內(nèi)的數(shù)據(jù)域202、數(shù)據(jù)定義偽操作-數(shù)據(jù)內(nèi)存表 MAP 0,R9 consta FIELD4 constbFIELD4 xFIELD8 yFIELD8 string FIELD16使用:LDRR0,constb ;LDRR0,[R9,#4]

MAP、FIELD基于相對地址的內(nèi)存表舉例內(nèi)存表中各數(shù)據(jù)域的實際內(nèi)存地址不是基于一個固定的地址,而是基于LDR指令執(zhí)行R9寄存器中的內(nèi)容。;內(nèi)存表的首地址為0+R9212、數(shù)據(jù)定義偽操作——連續(xù)內(nèi)存分配DataSPACE100;分配100字節(jié)的內(nèi)存單元,并初始化為0{label}SPACEexpr語法格式222、數(shù)據(jù)定義偽操作-字節(jié)內(nèi)存分配偽操作語法格式作用LTORGLTORG聲明一個數(shù)據(jù)緩沖池(也稱為文字池)的開始。MAPMAPexpr{,base-register}定義一個結構化的內(nèi)存表的首地址=expr{+BR}FIELD{label}FIELDexpr定義一個結構化內(nèi)存表中的數(shù)據(jù)域長度expr(B)。SPACE{label}SPACEexpr分配一塊連續(xù)內(nèi)存單元expr(B),并用0初始化。DCB{label}DCBexpr{,expr}分配一段字節(jié)內(nèi)存單元,并用expr初始化。DCD/DCDU{label}DCDexpr{,expr}…分配一段字內(nèi)存單元。DCDO{label}DCDOexpr{,expr}…分配一段字對齊的字內(nèi)存單元。DCFD/DCFDU{label}DCFD{U}fpliteral{,fpliteral}…為雙精度的浮點數(shù)分配字對齊的內(nèi)存單元。DCFS/DCFSU{label}DCFS{U}fpliteral{,fpliteral}…為單精度的浮點數(shù)分配字對齊的內(nèi)存單元。DCI{label}DCIexpr{,expr}…在ARM代碼中分配一段字對齊的內(nèi)存單元;在Thumb代碼中,分配一段半字對齊的半字內(nèi)存單元。DCQ/DCQU{label}DCQ{U}{﹣}literal{,{﹣}literal}…分配一段以雙字(8個字節(jié))為單位的內(nèi)存DCW/DCWU{label}DCW{U}expr{,expr}…DCW用于分配一段半字對齊的半字內(nèi)存單元。232、數(shù)據(jù)定義偽操作-字節(jié)內(nèi)存分配DCBStringDCB“student” ;以字節(jié)為單位“=”是DCB的同義詞{label}DCBexpr{,expr}語法格式242、數(shù)據(jù)定義偽操作-字內(nèi)存分配DCDaddrMOVR0,R1…Data1DCD1,5,20;第一個內(nèi)存單元前填補字節(jié)保證字對齊,其值分別為1、5、20{label}DCDexpr{,expr}語法格式252、符號和數(shù)據(jù)定義偽操作-說明變量:通常具有“值可變”和“分配內(nèi)存”兩個特性。變量供指令使用。例如用DCB/D定義的符號偽變量:只具有“值可變”一個特性。供編譯器使用,在程序編譯后,所有的偽變量將被真值替換。例如用GBLx定義的符號。實例:

GBLA arithmeticarithmitic SETA 0xEF MOV R0, #arithmetic編譯后只有一行代碼為:

MOV R0, #0xEF26偽操作符號定義(SymbolDefinition)

偽操作內(nèi)存分配(數(shù)據(jù)定義)(DataDefinition)

偽操作匯編控制(AssemblyControl)

偽操作

其他

(Miscellaneous)

偽操作

273、匯編控制偽操作

偽操作語法格式作用IFELSEENDIFIFlogicalexpression…{ELSE…}ENDIF能夠根據(jù)條件把一段源代碼包括在匯編語言程序內(nèi)或者將其排除在程序之外。WHILEWENDWHILElogicalexpression…WEND能夠根據(jù)條件重復匯編相同的一段源代碼。MACRO

MENDMEXITMACRO{$label}macroname{$parameter{,$parameter}…}…;宏代碼{MEXIT};根據(jù)需要插入…;宏代碼MENDMACRO標識宏定義的開始,MEND標識宏定義的結束。MEXIT用于從宏中跳轉出去。用MACRO和MEND定義的一段代碼,稱為宏定義體。通過宏名稱來調(diào)用宏。283、匯編控制偽操作 ——IF,ELSE及ENDIFIFlogicalexpressionInstructionsorderectives{ELSEInstructionsorderectives}ENDIF語法格式293、匯編控制偽操作 ——IF,ELSE及ENDIF IF Variable=16 BNESUB1 LDRR0,=SUB0 BX R0 ELSE BNESUB0 … ENDIF303、匯編控制偽操作 ——WHILE及WENDWHILElogicalexpressionInstructionsorderectives WEND語法格式313、匯編控制偽操作 ——WHILE及WENDcount SETA 1 WHILE count<=4count SETAcount+1 … WEND323、匯編控制偽操作 ——MACRO及MENDMACRO$labelmacroname$parameter1,$parameter2…;code…;codeMEND語法格式333、匯編控制偽操作 MACRO$labelTestAndBranch$ds,$re,$aa$label CMP$re,#0 B$aa $ds MENDtestTestAndBranchnzero,r0,NEtest CMPr0,#0 BNE nzero宏定義:宏調(diào)用:宏展開:34偽操作符號定義(SymbolDefinition)

偽操作內(nèi)存分配(數(shù)據(jù)定義)(DataDefinition)

偽操作匯編控制(AssemblyControl)

偽操作其他

(Miscellaneous)

偽操作

354、其他偽操作偽操作語法格式作用CODE16CODE16告訴匯編編譯器后面的指令序列為16位的Thumb指令CODE32CODE32告訴匯編編譯器后面的指令序列為32位的ARM指令。EQUnameEQUexpr{,type}為數(shù)字常量、基于寄存器的值和程序中的標號(基于PC的值)定義一個字符名稱。AREAAREAsectionname{,attr}{,attr}…定義一個代碼段或者數(shù)據(jù)段。ENTRYENTRY指定程序的入口點。ENDEND告訴編譯器已經(jīng)到了源程序結尾。ALIGNALIGN{expr{,offset}}通過添加補丁字節(jié)使當前位置滿足一定的對齊方式。EXPORT/GLOBALEXPORTsymbol{[WEAK]}聲明一個符號可以被其他文件引用,相當于聲明了一個全局變量。IMPORTIMPORTsymbol{[WEAK]}告訴編譯器當前的符號不是在本源文件中定義的,而是在其他源文件中定義的,在本源文件中可能引用該符號。EXTERNEXTERNsymbol{〔WEAK〕}告訴編譯器當前的符號不是在本源文件中定義的,而是在其他源文件中定義的,在本源文件中可能引用該符號。GET/INCLUDEGET

將一個源文件包含到當前源文件中,并將被包含的文件在其當前位置進行匯編處理。INCBININCBIN將一個文件包含到當前源文件中,被包含的文件不進行匯編處理。KEEPKEEP{symbol}告訴編譯器將局部符號包含在目標文件的符號表中。NOFPNOFP禁止源程序中包含浮點運算指令。REQUIREREQUIRElable指定段之間的相互依賴關系。RNnameRNexpr為一個特定的寄存器定義名稱。ROUT{name}ROUT定義局部變量的有效范圍。364、其他偽操作AREAsectionname{,attr}{,attr}…定義一個代碼段或者數(shù)據(jù)段。ENTRY指定程序的入口點。CODE32告訴匯編編譯器后面的指令序列為32位的ARM指令。END告訴編譯器已經(jīng)到了源程序結尾。nameEQUexpr{,type}為數(shù)字常量、基于寄存器的值和程序中的標號(基于PC的值)定義一個字符名稱。ALIGN{expr{,offset}}通過添加補丁字節(jié)使當前位置滿足一定的對齊方式。EXPORT/GLOBALsymbol{[WEAK]}聲明一個符號可以被其他文件引用,相當于聲明了一個全局變量。IMPORT/EXTERNsymbol{[WEAK]}告訴編譯器當前的符號不是在本源文件中定義的,而是在其他源文件中定義的,在本源文件中可能引用該符號。GET/INCLUDE將一個源文件包含到當前源文件中,并將被包含的文件在其當前位置進行匯編處理。nameRNexpr為一個特定的寄存器定義名稱。37段定義在ARM(Thumb)匯編語言程序中,以程序段為單位組織代碼。段是相對獨立的指令或數(shù)據(jù)序列,具有特定的名稱。段可以分為代碼段和數(shù)據(jù)段,代碼段的內(nèi)容為執(zhí)行代碼,數(shù)據(jù)段存放代碼運行時需要用到的數(shù)據(jù)。一個匯編程序至少應該有一個代碼段,當程序較長時,可以分割為多個代碼段和數(shù)據(jù)段。38段定義代碼段的例子:

AREAHello,CODE,READONLY

;聲明代碼段Hello ENTRY ;程序的入口點STARTMOVR7,#10 MOVR6,#5 ADDR6,R6,R7 ;R6=R6+R7 END ;每一個匯編文件 ;都要以END結束39段定義數(shù)據(jù)的例子:

AREADatearea,DATA,NOINIT ;聲明數(shù)據(jù)段Datearea DATASPACESPACE100;分配連續(xù)100字節(jié)的存儲單元,并初始化為零40ENTRYENTRY指示符指定程序的入口點語法格式ENTRY使用說明一個程序(可以包含多個源文件)中至少要有一個ENTRY(可以有多個ENTRY),但一個源文件中最多只能有一個ENTRY(可以沒有ENTRY)。示例AREAexample,CODE,READONLYENTRY;應用程序的入口點41CODE16和CODE32CODE16指示符告訴匯編編譯器后面的指令序列為16位的Thumb指令。CODE32指示符告訴匯編編譯器后面的指令序列為32位的ARM指令。語法格式CODE16CODE32使用說明CODE16指示符和CODE32指示符只是告訴編譯器后面指令的類型,該指示符本身并不進行程序狀態(tài)的切換。42CODE16/CODE32舉例 在下面的例子中,程序先在ARM狀態(tài)下執(zhí)行,然后通過BX指令切換到Thumb狀態(tài),并跳轉到相應的Thumb指令處執(zhí)行。在Thumb程序入口處用CODE16指示符標識下面的指令為Thumb指令。參看下面的指令段:

………………. AREAChangeState,CODE,READONLY CODE32 ;指示下面的指令為ARM指令 LDRr0,=start+1 BXr0 ;切換到Thumb,并跳轉到start處執(zhí)行 CODE16 ;指示下面的指令為Thumb指令start MOVr1,#1043ENDEND指示符告訴編譯器已經(jīng)到了源程序結尾。語法格式:END使用說明:每一個匯編源程序都包含END指示符,以告訴本源程序的結束。示例: AREAexampleCODE,READONLY………………END………44EXPORTEXRORT聲明一個符號可以被其他文件引用。相當于聲明了一個全局變量。GLOBAL是EXPORT的同義詞。語法格式EXPORTsymbol{[WEAK]}其中,symbol為聲明的符號名稱,大小寫敏感。[WEAK]選項聲明其他的同名符號優(yōu)先于本符號被引用。使用說明使用EXPORT指示符聲明一個源文件中的符號,使得該符號可以被其他源文件引用。示例AREAExample,CODE,READONLYEXPORTDo_Add;函數(shù)名稱DoAdd可以被引用Do_AddADDr0,r0,r145IMPORTIMPORT指示符告訴編譯器當前的符號不是在本源文件中定義的,而是在其他源文件中定義的,在本源文件中可能引用該符號,而且不論本源文件是否實際引用該符號,該符號都將被加入到本源文件的符號表中。語法格式IMPORTsymbol{[WEAK]}symbol為聲明的符號的名稱。它是區(qū)分大小寫的。[WEAK]指定這個選項后,如果symbol在所有的源文件中都沒有被定義,編譯器也不會產(chǎn)生任何錯誤信息,同時編譯器也不會到當前沒有被INCLUDE進來的庫中去查找該符號。46EXTERNEXTERN指示符告訴編譯器當前的符號不是在本源文件中定義的,而是在其他源文件中定義的,在本源文件中可能引用該符號。如果本源文件沒有實際引用該符號,該符號都將不會被加入到本源文件的符號表中。語法格式EXTERNsymbol{[WEAK]}symbol為聲明的符號的名稱。它是區(qū)分大小寫的。[WEAK]指定該選項后,如果symbol在所有的源文件中都沒有被定義,編譯器也不會產(chǎn)生任何錯誤信息,同時編譯器也不會到當前沒有被INCLUDE進來的庫中去查找該符號。47ARM匯編注意事項

--常用符號在匯編語言程序設計中,經(jīng)常使用各種符號代替地址、變量和常量等,以增加程序的可讀性。盡管符號的命名由編程者決定,但并不是任意的,必須遵循以下的約定:

—符號區(qū)分大小寫,同名的大、小寫符號會被編譯器認為是兩個不同的符號。 —符號在其作用范圍內(nèi)必須唯一。 —自定義的符號名不能與系統(tǒng)的保留字相同。 —符號名不應與指令或偽指令同名。48基于Linux的GNU匯編器格式49GNU格式的ARM匯編語言程序設計GNU格式ARM匯編語言程序主要用于基于ARM硬件平臺和Linux操作系統(tǒng)的嵌入式開發(fā)。50基于ARM處理器的GNU匯編語句格式如下:[<label>:][<instructionordircetive>]@注釋其中的第1個字段label是標號,第2個字段instructionordircetive是指令或者GNU的匯編指示符。①所有標號必須在一行的頂格書寫,并且加冒號(:);②所有指令均不能頂格寫;③大小寫敏感;④注釋使用符號“@”51Linux下的ARM匯編.text段代表代碼段的開始。匯編程序中的段名系統(tǒng)預定義的段名有.text、.data、.bss等,每一個段從某一段名開始,至下一個段名的出現(xiàn)或者文件的結尾結束.textmovr3,#0x1234tstr3,#0x5678… .data段代表數(shù)據(jù)段的開始。.bss段代表未初始化數(shù)據(jù)段的開始。.data.byte12,34,36,78.string“hello!”… .bss.short0,0,0.long0,0,0,0… 52Linux下的ARM匯編匯編程序中的常數(shù)——數(shù)據(jù)定義偽操作單字節(jié)定義以.byte開頭.byte1,2,0b01,0x34,072,’s’.short偽操作定義雙字節(jié)數(shù)據(jù).short0x1234,60000.long偽操作定義4字節(jié)數(shù)據(jù).long0x12345678,23876565.quad偽操作定義8字節(jié).quad0x1234567890abcd53Linux下的ARM匯編匯編程序中的常數(shù)——重復定義偽操作.rept.rept 重復次數(shù)數(shù)據(jù)定義.endr.rept 3.byte0x23.endr.byte0x23.byte0x23.byte0x23格式54Linux下的ARM匯編匯編程序中的常數(shù)——賦值語句.equ(.set) 變量名,表達式.equ abc3abc=3格式55Linux下ARM匯編的常用偽操作.end偽操作.end偽操作表明源文件的結束如果.end之后還有代碼,這些代碼將不被編譯。 area scopy,code,readonly exportstrcopystrcopy ;r0pointstodestinationstring ;r1pointstosourcestring ldrb r2,[r1],#1 strb r2,[r0],#1 cmp r2,#0 bne strcopy mov pc,lr .end ldrb r2,[r1],#1 strb r2,[r0],#1 cmp r2,#0無效代碼!56Linux下ARM匯編的常用偽操作.include偽操作.include偽操作可以將指定的文件在使用.include的地方展開,一般是頭文件.include “myarmasm.h”.incbin偽操作可以將原封不動的一個二進制文件編譯到當前文件中.incbin “file”[,skip[,count]]skip表明是從文件開始跳過skip個字節(jié)開始讀取文件,count是讀取的字數(shù)。57Linux下ARM匯編的常用偽操作.if偽操作.include偽操作可以根據(jù)一個表達式的值決定是否要編譯下面的代碼,用.endif偽操作表示條件判斷的結束,中間可使用.else來決定.if的條件不滿足時應編譯哪部分代碼.ifdef symbol判斷symbol是否定義.ifcstring1,string2判斷字符串string1和string2是否相等,字符串可用單引號括起來.ifeqexpression判斷expression的值是否為0.ifeqsstring1,string2判斷string1和string2是否相等,字符串必須用雙引號括起來.ifgeexpression判斷expression的值是否大于等于0.ifgtabsoluteexpression判斷expression的值是否大于0.ifleexpression判斷expression的值是否小于等于0.ifltabsoluteexpression判斷expression的值是否小于0.ifncstring1,string2判斷字符串string1和string2是否不相等.ifndef symbol判斷symbol是否未定義.ifneexpression判斷expression的值是否不等于0.ifnesstring1,string2判斷string1和string2是否不相等58Linux下ARM匯編的常用偽操作.global偽操作.global偽操作用來定義一個全局的符號.global symbol.globl symbol59Linux下ARM匯編的常用偽操作ARM特有的偽操作.code偽操作用來選擇ARM或者Thumb指令集.code 表達式.thumb偽操作等同于.code16.arm偽操作等同于.code32.force_thumb用來強制目標處理器選擇thumb指令集而不管處理器是否支持.thumb_func用來指明一個函數(shù)是thumb指令集的函數(shù)60ARM匯編與C的混合編程61ARM文件格式ARM源程序文件的后綴名如下表示:ARM源程序文件(即源文件)為文件格式,可以使用任一文本編輯器編寫程序代碼。在一個程序中,至少要有一個匯編源文件和C程序文件,可以有多個源文件和C程序文件,或C文件和源文件兩者的組合。62ARM語言選擇由于高級編程語言隱藏了CPU執(zhí)行指令的許多細節(jié),因此在只關心系統(tǒng)所具有功能,采用高級語言編寫程序更為合適。但是,CPU執(zhí)行指令的細節(jié)差異會反應在系統(tǒng)的非功能特性上,例如系統(tǒng)程序的規(guī)模和運行速度。因此,掌握匯編語言程序設計對于嵌入式系統(tǒng)的設計者來說是非常必要的。

63匯編語言和C語言混合編程方式:匯編程序中調(diào)用C程序C程序中調(diào)用匯編程序C程序中內(nèi)嵌匯編語句從匯編程序中訪問C程序變量64ATPCSATPCS(ARM-ThumbProcedureCallStandard)規(guī)定了一些子程序間調(diào)用的基本規(guī)則,這些規(guī)則包括子程序調(diào)用過程中寄存器的使用規(guī)則,數(shù)據(jù)棧的使用規(guī)則,參數(shù)的傳遞規(guī)則。有了這些規(guī)則之后,單獨編譯的C語言程序就可以和匯編程序相互調(diào)用。使用C語言編譯器編譯的C語言子程序滿足用戶指定的ATPCS類型。而對于匯編語言來說,則需要用戶來保證各個子程序滿足ATPCS的要求。65ATPCS規(guī)范要點寄存器的使用規(guī)則堆棧使用規(guī)則參數(shù)傳遞規(guī)則子程序結果返回規(guī)則66寄存器的使用規(guī)則子程序間通過寄存器R0~R3來傳遞參數(shù)。寄存器R0~R3可記作a0~a3。被調(diào)用的子程序在返回前無需恢復寄存器R0~R3的內(nèi)容。在子程序中,使用寄存器R4~R11來保存局部變量。寄存器R4~R11可以記作v1~v8。子程序進入時必須保存這些寄存器的值,在返回前必須恢復這些寄存器的值。在Thumb程序中,通常只能使用寄存器R4~R7來保存局部變量。寄存器R12用作過程調(diào)用中間臨時寄存器,記作IP。在子程序之間的連接代碼段中常常有這種使用規(guī)則。67寄存器的使用規(guī)則(續(xù))寄存器R13用作堆棧指針,記作SP。在子程序中寄存器R13不能用作其他用途。寄存器SP在進入子程序時的值和退出子程序時的值必須相等。寄存器R14稱為連接寄存器,記作LR。它用于保存子程序的返回地址。如果在子程序中保存了返回地址,寄存器R14則可以用作其他用途。寄存器R15是程序計數(shù)器,記作PC。它不能用作其它用途。68堆棧使用規(guī)則ATPCS規(guī)定堆棧為FD類型,即滿遞減堆棧,并且對堆棧的操作是8字節(jié)對齊。69參數(shù)傳遞規(guī)則根據(jù)參數(shù)個數(shù)是否固定,可以將子程序分為參數(shù)個數(shù)固定的子程序和參數(shù)個數(shù)可變化的子程序。70參數(shù)個數(shù)可變子程序參數(shù)傳遞規(guī)則對于參數(shù)個數(shù)可變的子程序,當參數(shù)個數(shù)不超過4個時,可以使用寄存器R0~R3來傳遞參數(shù);當參數(shù)超過4個時,還可以使用堆棧來傳遞參數(shù)。71參數(shù)個數(shù)固定子程序參數(shù)傳遞規(guī)則對于參數(shù)個數(shù)固定的子程序,第一個整數(shù)參數(shù)通過寄存器R0~R3來傳遞,其他參數(shù)通過堆棧傳遞。浮點參數(shù)規(guī)則:各個浮點參數(shù)按順序處理;為每個浮點參數(shù)分配FP寄存器。72子程序結果返回規(guī)則子程序中結果返回的規(guī)則如下:結果為一個32位整數(shù)時,可以通過寄存器R0返回;結果為一個64位整數(shù)時,可以通過寄存器R0和Rl返回;結果為一個浮點數(shù)時,可以通過浮點運算部件的寄存器f0、d0或s0來返回;結果為復合型浮點數(shù)(如復數(shù))時,可以通過寄存器f0~fn或d0~dn來返回;對于位數(shù)更多的結果,需要通過內(nèi)存來傳遞。73匯編語言和C語言混合編程方式:匯編程序中調(diào)用C程序C程序中調(diào)用匯編程序C程序中內(nèi)嵌匯編語句從匯編程序中訪問C程序變量74匯編調(diào)用C舉例//c程序g()返回5個整數(shù)的和 intg(inta,intb,intc,intd,inte){returna+b+c+d+e;};匯編程序調(diào)用c程序g()計算5個整數(shù)i,2*i,3*i,4*i,5*i的和AREAf,CODE,READONLYIMPORTg;使用偽操作數(shù)IMPORT聲明c程序g()STRlr,[sp,#-4]!;保存返回地址ADDr1,r0,r0 ;假設進入程序f時,r0中的值為i,r1值設為2*iADDr2,r1,r0 ;r2的值設為3*iADDr3,r1,r2 ;r3的值設為5*iSTRr3,[sp,#-4]!;第五個參數(shù)5*i通過數(shù)據(jù)棧傳遞ADDr3,r1,r1 ;r3值設為4*iBLg ;調(diào)用c程序g()ADDsp,sp,#4 ;調(diào)整數(shù)據(jù)棧指針,準備返回LDRpc,[sp],#4;返回END75匯編調(diào)用C語言C文件自動使用R0、R1、R2、R3來傳遞第一個、第二個、第三個和第四個參數(shù)。如果參數(shù)多于4個,剩余的參數(shù)將被壓入堆棧。intg(inta,intb,intc,intd,inte){returna+b+c+d+e;}g PROC ADD r0,r0,r1 ADD r0,r0,r2 LDR r12,[sp,#0] ADD r0,r0,r3 ADD r0,r0,r12 MOV pc,lr ENDP EXPORT g76匯編語言和C語言混合編程方式:匯編程序中調(diào)用C程序C程序中調(diào)用匯編程序C程序中內(nèi)嵌匯編語句從匯編程序中訪問C程序變量77C語言調(diào)用匯編strtest.c#include<stdio.h>externvoidstrcopy(char*d,constchar*s);intmain(){ constchar*srcstr=“Firststring-source”; chardststr[]=“Secondstring-destination”; /*dststrisanarraysincewe’regoingtochangeit

溫馨提示

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

最新文檔

評論

0/150

提交評論