




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
本章主要介紹的內(nèi)容:
ARM匯編語言的偽操作、宏指令、偽指令、匯編語言程序設(shè)計、C與匯編語言混合編程和軟件開發(fā)環(huán)境等。重點內(nèi)容:
ARM匯編語言的偽操作、宏指令、偽指令、匯編語言程序設(shè)計、C與匯編語言混合編程和ATPCS。目的和要求:掌握ARM匯編語言的偽操作、宏指令、偽指令、匯編語言程序設(shè)計、C與匯編語言混合編程和軟件開發(fā)環(huán)境等。第4章基于ARM的嵌入式程序設(shè)計第4章基于ARM的嵌入式程序設(shè)計1.ARM匯編語言的偽操作、宏指令與偽指令2.ARM匯編語言程序設(shè)計3.嵌入式C語言程序設(shè)計基礎(chǔ)4.嵌入式C語言程序設(shè)計實例5.嵌入式C語言程序設(shè)計技巧6.C與匯編語言混合編程7.基于EmbestIDEforARM環(huán)境的軟件開發(fā)實例4.1ARM匯編語言的偽操作宏指令與偽指令1.兩種常見的ARM編譯開發(fā)環(huán)境2.ADS編譯環(huán)境下的偽操作和宏指令3.GNU編譯環(huán)境下的偽操作和宏指令4.ARM匯編語言的偽指令4.1.1兩種常見的ARM編譯開發(fā)環(huán)境1.ADS/SDTIDE開發(fā)環(huán)境
由ARM公司開發(fā),使用了CodeWarrior公司的編譯器;
ARM公司最新的開發(fā)環(huán)境是RealViewMDK。2.集成了GNU開發(fā)工具的IDE開發(fā)環(huán)境
由GNU的匯編器as、交叉編譯器gcc和鏈接器ld等組成。4.1.2ADS編譯環(huán)境下的偽操作和宏指令A(yù)DS編譯環(huán)境下的偽操作可分為以下幾類:1.符號定義(SymbolDefinition)偽操作2.數(shù)據(jù)定義(DataDefinition)偽操作3.匯編控制(AssemblyControl)偽操作4.信息報告(Reporting)偽操作5.其他(Miscellaneous)偽操作1.符號定義類偽指令4.1.2ADS編譯環(huán)境下的偽操作和宏指令
符號定義偽操作用于定義ARM匯編程序中的變量,對變量進行賦值以及定義寄存器名稱。
包括以下偽操作:
(1)GBLA、GBLL、GBLS:聲明全局變量。
(2)LCLS、LCLL、LCLD:聲明局部變量。
(3)SETA、SETL、SETS:給變量賦值。
(4)RLIST:為通用寄存器列表定義名稱。
(5)CN:為協(xié)處理器的寄存器定義名稱。
(6)CP:為協(xié)處理器定義名稱。
(7)DN、SN:為VFP的寄存器定義名稱。
(8)FN:為FPA的浮點寄存器定義名稱。偽操作語法格式作用GBLAGBLAVariable聲明一個全局的算術(shù)變量,并將其初始化成0。GBLLGBLLVariable聲明一個全局的邏輯變量,并將其初始化成{FALSE}。GBLSGBLSVariable聲明一個全局的字符串變量,并將其初始化成空串“”。LCLALCLAVariable聲明一個局部的算術(shù)變量,并將其初始化成0。LCLLLCLLVariable聲明一個局部的邏輯變量,并將其初始化成{FALSE}。LCLSLCLSVariable聲明一個局部的串變量,并將其初始化成空串“”。SETASETAVariableexpr給一個全局或局部算術(shù)變量賦值。SETLSETLVariableexpr給一個全局或局部邏輯變量賦值。SETSSETSVariableexpr給一個全局或局部字符串變量賦值。RLISTnameRLIST{listofregisters}為一個通用寄存器列表定義名稱。CNnameCNexpr為一個協(xié)處理器的寄存器定義名稱。CPnameCPexpr為一個協(xié)處理器定義名稱。DN/SNnameDN/SNexprDN/SN為一個雙精度/單精度的VFP寄存器定義名稱。FNnameFNexpr為一個FPA浮點寄存器定義名稱。1.符號定義類偽指令4.1.2ADS編譯環(huán)境下的偽操作和宏指令示例:
GBLLPLL_ON_STARTPLL_ON_STARTSETL{TRUE}
GBLAENTRY_BUS_WIDTHENTRY_BUS_WIDTHSETA16;定義全局邏輯變量PLL_ON_START;給全局邏輯變量PLL_ON_START賦值;定義全局數(shù)字變量ENTRY_BUS_WIDTH;給全局數(shù)字變量ENTRY_BUS_WIDTH賦值4.1.2ADS編譯環(huán)境下的偽操作和宏指令1.符號定義類偽指令偽操作語法格式作用LTORGLTORG聲明一個數(shù)據(jù)緩沖池(也稱為文字池)的開始。MAPMAPexpr{,base-register}定義一個結(jié)構(gòu)化的內(nèi)存表(StorageMap)的首地址。FIELD{label}FIELDexpr定義一個結(jié)構(gòu)化內(nèi)存表中的數(shù)據(jù)域,即表的長度。SPACE{label}SPACEexpr分配一塊連續(xù)內(nèi)存單元(字節(jié)),并用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)存單元。2.數(shù)據(jù)定義偽操作4.1.2ADS編譯環(huán)境下的偽操作和宏指令1.SPACE
分配一片連續(xù)的存儲區(qū)域并初始化為0。其中,表達式表示要分配的字節(jié)數(shù)。
DataSpaceSPACE100
;分配連續(xù)100字節(jié)的存儲單元并初始化為0。2.MAP和FIELD
MAP偽指令用于定義一個結(jié)構(gòu)化的內(nèi)存表的首地址。MAP也可用“^”代替。
FIELD偽指令用于定義一個結(jié)構(gòu)化的內(nèi)存表的數(shù)據(jù)域。FIELD也可用“#”代替。
MAP0X1000;定義結(jié)構(gòu)化內(nèi)存表首地址的值為0X1000FirFIELD16;定義Fir的長度為16字節(jié),位置為0X1008SecFIELD32;定義Sec的長度為32字節(jié),位置為0X1010
ThrFIELD256;定義Thr的長度為256字節(jié),位置為0X10303.存儲單元分配
DCBDCDDCW4.1.2ADS編譯環(huán)境下的偽操作和宏指令2.數(shù)據(jù)定義偽操作3.匯編控制偽操作偽操作語法格式作用IFELSEENDIFIFlogicalexpression…{ELSE…}ENDIF能夠根據(jù)條件把一段源代碼包括在匯編語言程序內(nèi)或者將其排除在程序之外。WHILEWENDWHILElogicalexpression…WEND能夠根據(jù)條件重復(fù)匯編相同的一段源代碼。MACROMENDMEXITMACRO{$label}macroname{$parameter{,$parameter}…}… ;宏代碼MENDMACRO標(biāo)識宏定義的開始,MEND標(biāo)識宏定義的結(jié)束。MEXIT用于從宏中跳轉(zhuǎn)出去。用MACRO和MEND定義的一段代碼,稱為宏定義體。通過宏名稱來調(diào)用宏。4.1.2ADS編譯環(huán)境下的偽操作和宏指令偽操作語法格式作用ASSERTASSERTlogicalexpression對匯編程序的第二遍掃描中,如果其中ASSERT中條件不成立,ASSERT偽操作將報告該錯誤信息。INFOINFOnumeric-expression,string-expression在匯編處理過程的第一遍掃描或者第二遍掃描時INFO偽操作報告診斷信息。OPTOPTn通過OPT偽操作可以在源程序中設(shè)置列表選項。TTL
TTLtitle在列表文件的每一頁的開頭插入一個標(biāo)題。SUBTSUBTsubtitle在列表文件的每一頁的開頭插入一個子標(biāo)題。4.信息報告?zhèn)尾僮?.1.2ADS編譯環(huán)境下的偽操作和宏指令偽操作語法格式作用CODE16CODE16告訴匯編編譯器后面的指令序列為16位的Thumb指令CODE32CODE32告訴匯編編譯器后面的指令序列為32位的ARM指令。EQUnameEQUexpr{,type}為數(shù)字常量、基于寄存器的值和程序中的標(biāo)號(基于PC的值)定義一個字符名稱。AREAAREAsectionname{,attr}{,attr}…定義一個代碼段或者數(shù)據(jù)段。ENTRYENTRY指定程序的入口點。ENDEND告訴編譯器已經(jīng)到了源程序結(jié)尾。ALIGNALIGN{expr{,offset}}通過添加補丁字節(jié)使當(dāng)前位置滿足一定的對齊方式。EXPORT/GLOBALEXPORTsymbol{[WEAK]}聲明一個符號可以被其他文件引用,相當(dāng)于聲明了一個全局變量。IMPORTIMPORTsymbol{[WEAK]}告訴編譯器當(dāng)前的符號不是在本源文件中定義的,而是在其他源文件中定義的,在本源文件中可能引用該符號。EXTERNEXTERNsymbol{[WEAK]}告訴編譯器當(dāng)前的符號不是在本源文件中定義的,而是在其他源文件中定義的,在本源文件中可能引用該符號。GET/INCLUDEGETfilename將一個源文件包含到當(dāng)前源文件中,并將被包含的文件在其當(dāng)前位置進行匯編處理。INCBININCBINfilename將一個文件包含到當(dāng)前源文件中,被包含的文件不進行匯編處理。KEEPKEEP{symbol}告訴編譯器將局部符號包含在目標(biāo)文件的符號表中。NOFPNOFP禁止源程序中包含浮點運算指令。REQUIREREQUIRElable指定段之間的相互依賴關(guān)系。RNnameRNexpr為一個特定的寄存器定義名稱。ROUT{name}ROUT定義局部變量的有效范圍。5.其他偽操作1.AREA
用于定義一個代碼段或數(shù)據(jù)段。
AREAInit,CODE,READONLYAREARamData,DATA,READWRITE2.ALIGN
可通過添加字節(jié)的方式,使當(dāng)前位置滿足一定的對齊方式。3.EXPORT、GLOBAL、IMPORT、EXTERN
引用指令。4.GET、INCLUDE、INCBIN
包含指令。4.1.2ADS編譯環(huán)境下的偽操作和宏指令
GEToption.sGETmemcfg.sGET2410addr.s……AREAInit,CODE,READONLYENTRYBResetHandle……ResetHandle
ldrr0,=WTCON;禁止看門狗
ldrr1,=0x0
strr1,[r0]
ldrr0,=INTMASK;禁止所有中斷
ldrr1,=0xffffffff
strr1,[r0]……END首先用GET偽指令將3個源文件包含到當(dāng)前的源文件中,被包含的源文件在當(dāng)前位置進行匯編處理。4.1.2ADS編譯環(huán)境下的偽操作和宏指令4.1.3GNU編譯環(huán)境下的偽操作和宏指令
GNU編譯環(huán)境下的偽操作可分為以下幾類:
1.常量編譯控制偽操作
2.匯編程序代碼控制偽操作
3.宏及條件編譯控制偽操作
4.其他偽操作1.常量編譯控制偽操作
偽操作語法格式作用.byte.byteexpr{,expr}…分配一段字節(jié)內(nèi)存單元,并用expr初始化。.hword/.short.hword
expr{,expr}…分配一段半字內(nèi)存單元,并用expr初始化。.ascii.ascii
expr{,expr}…定義字符串expr(非零結(jié)束符)。.asciz/.string.asciz
expr{,expr}…定義字符串expr(以/0為結(jié)束符)。.float/.single.floatexpr{,expr}…定義一個32bitIEEE浮點數(shù)expr。.double.doubleexpr{,expr}…定義64bitIEEE浮點數(shù)expr。word/.long/.int.wordexpr{,expr}…分配一段字內(nèi)存單元,并用expr初始化。.fill.fillrepeat{,size}{,value}分配一段字節(jié)內(nèi)存單元,用size長度value填充repeat次。.zero.zerosize分配一段字節(jié)內(nèi)存單元,并用0填充內(nèi)存。.space/.skip.spacesize{,value}分配一段內(nèi)存單元,用value將內(nèi)存單元初始化。4.1.3GNU編譯環(huán)境下的偽操作和宏指令
偽操作語法格式作用.section.sectionexpr定義域中包含的段。.text.text{subsection}將操作符開始的代碼編譯到代碼段或代碼段子段。.data.data{subsection}將操作符開始的數(shù)據(jù)編譯到數(shù)據(jù)段或數(shù)據(jù)段子段。.bss.bss{subsection}將變量存放到.bss段或.bss段的子段。.code16/.thumb.code16.thumb表明當(dāng)前匯編指令的指令集選擇Thumb指令集。.code32/.arm.code32.arm表明當(dāng)前匯編指令的指令集選擇ARM指令集。.end.end標(biāo)記匯編文件的結(jié)束行,即標(biāo)號后的代碼不作處理。.include.include“filename”將一個源文件包含到當(dāng)前源文件中。.align/.balign.align{alignment}{,fill}{,max}通過添加填充字節(jié)使當(dāng)前位置滿足一定的對齊方式。2.匯編程序代碼控制偽操作4.1.3GNU編譯環(huán)境下的偽操作和宏指令
偽操作語法格式作用.macro.exitm.endm.macroacroname
{parameter{,parameter}…}
….endm.macro偽操作標(biāo)識宏定義的開始,.endm標(biāo)識宏定義的結(jié)束。用.macro及.endm定義一段代碼,稱為宏定義體。.exitm偽操作用于提前退出宏。.ifdef.else.endif.ifdefcondition….else….endif當(dāng)滿足某條件時對一組語句進行編譯,而當(dāng)條件不滿足時則編譯另一組語句。其中else可以缺省。3.宏及條件編譯控制偽操作4.1.3GNU編譯環(huán)境下的偽操作和宏指令
偽操作語法格式作用.eject.eject在匯編符號列表文件中插入一分頁符。.list.list產(chǎn)生匯編列表(從.list到.nolist)。.nolist.nolist表示匯編列表結(jié)束處。.title.title“heading”使用“heading”作為標(biāo)題。.sbttl.sbttl“heading”使用“heading”作為子標(biāo)題。.ltorg.ltorg在當(dāng)前段的當(dāng)前地址(字對齊)產(chǎn)生一個文字池。.req.reqname,expr為一個特定的寄存器定義名稱。.err.err使編譯時產(chǎn)生錯誤報告。.print.printstring打印信息到標(biāo)準(zhǔn)輸出。.fail.failexpr編譯匯編文件時產(chǎn)生警告。4.其他偽操作4.1.3GNU編譯環(huán)境下的偽操作和宏指令
4.1.4ARM匯編語言的偽指令
偽指令語法格式作用和舉例ADRADR{cond}register,expr將基于PC或基于寄存器的地址值讀取到寄存器中。小范圍的地址讀取。例:startMOVR0,#10ADRR1,start
→SUBR1,PC,#0xCADRLADRL{cond}register,expr將基于PC或基于寄存器的地址值讀取到寄存器中。中等范圍的地址讀取。例:startMOVR0,#10ADRLR4,start+60000
→ADDR4,PC,#84ADDR4,R4,#59904LDRLDR{cond}register,=
[expr|label-expr]將一個32位的立即數(shù)或者一個地址值讀取到寄存器中。大范圍的地址讀取。例:
LDRR1,=0xFF
→
MOVR1,#0xFFNOPNOP在匯編時將被替換成ARM中的空操作。例:
LDRR1,=0xFFF→LDRR1,[PC,OFFSET_TO_LPOOL]……LTORGLPOOLDCD0xFFF例:
LDRR1,=ADDR1→LDRR1,[PC,OFFSET_TO_LPOOL]……LTORGLPOOLDCDADDR14.2ARM匯編語言程序設(shè)計1.ARM匯編中的文件格式2.ARM匯編語言語句格式3.ARM匯編語言編程的重點4.ARM匯編程序?qū)嵗?.2.1ARM匯編中的文件格式
ARM源程序文件(可簡稱為源文件)可以由任意一種文本編輯器來編寫程序代碼,它一般為文本格式。在ARM程序設(shè)計中,常用的源文件可簡單分為以下幾種:源程序文件文件名說
明匯編程序文件*.S用ARM匯編語言編寫的ARM程序或Thumb程序。C程序文件*.C用C語言編寫的程序代碼。頭文件*.H為了簡化源程序,把程序中常用到的常量命名、宏定義、數(shù)據(jù)結(jié)構(gòu)定義等等單獨放在一個文件中,一般稱為頭文件。4.2.2ARM匯編語言語句格式
ARM匯編語言語句格式如下所示:{symbol}{instruction|directive|pseudo-instruction}{;comment}
其中:
(1)symbol:為符號。
(2)instruction:為指令。
(3)directive:為偽操作。
(4)pseudo-instruction:為偽指令。
(5)comment:為語句的注釋。ARM匯編語言程序格式:
ARM匯編語言是以段(section)為單位來組織源文件的。段是相對獨立的、具有特定名稱的、不可分割的指令或者數(shù)據(jù)序列。段又可以分為代碼段和數(shù)據(jù)段,代碼段存放執(zhí)行代碼,數(shù)據(jù)段存放代碼運行時需要用到的數(shù)據(jù)。一個ARM源程序至少需要一個代碼段,大的程序可以包含多個代碼段和數(shù)據(jù)段。4.2.2ARM匯編語言語句格式
舉例說明ARM匯編語言源程序的基本結(jié)構(gòu):
AREAEXAMPLE,CODE,READONLYENTRYstartMOVr0,#10MOVr1,#3ADDr0,r0,r1END
本程序的程序體部分實現(xiàn)了一個簡單的加法運算。
4.2.2ARM匯編語言語句格式
4.2.3ARM匯編語言編程的重點1.ARM數(shù)據(jù)處理操作2.設(shè)置條件碼3.匯編語言子程序調(diào)用及返回4.跳轉(zhuǎn)表思想5.ARM與Thumb之間的狀態(tài)轉(zhuǎn)換及函數(shù)的相調(diào)用1.ARM數(shù)據(jù)處理操作ARM中數(shù)據(jù)的處理有以下三種形式:(1)簡單的寄存器操作(2)立即數(shù)操作(3)寄存器移位操作
其中32位立即數(shù)在32位指令中的編碼以及ARM特有的寄存器移位操作是數(shù)據(jù)處理方面的難點。4.2.3ARM匯編語言編程的重點2.設(shè)置條件碼
ARM的任何數(shù)據(jù)處理指令都能通過增加“S”操作碼來設(shè)置條件碼(N、Z、C和V)。
(1)條件執(zhí)行
ARM指令集不同尋常的特征是每條指令(除了某些v5T指令)都可以是條件執(zhí)行的。
ARM指令的編碼中都有一個條件域“cond”,它占據(jù)32位的指令域的高四位。cond31282704.2.3ARM匯編語言編程的重點2.設(shè)置條件碼
2、條件轉(zhuǎn)移
在程序中可以通過條件碼的使用讓微處理器決定是否進行轉(zhuǎn)移,還可用來控制循環(huán)的退出。轉(zhuǎn)移功能說明BBAL無條件的總是總是執(zhí)行轉(zhuǎn)移總是執(zhí)行轉(zhuǎn)移BEQBNE相等不等比較的結(jié)果為相等或零比較的結(jié)果為不等或非零BPLBMI正負結(jié)果為正數(shù)或零結(jié)果為負數(shù)BCCBLO無進位低于算術(shù)操作未得到進位無符號數(shù)比較,結(jié)果為低于BCSBHS有進位高于或相等算術(shù)操作得到了進位無符號數(shù)比較,結(jié)果為高于或相等BVCBVS無溢出有溢出有符號整數(shù)操作,未出現(xiàn)溢出有符號整數(shù)操作,出現(xiàn)溢出BGTBGE大于大于或相等有符號整數(shù)比較,結(jié)果為大于有符號整數(shù)比較,結(jié)果為大于或相等BLTBLE小于小于或相等有符號整數(shù)比較,結(jié)果為小于有符號整數(shù)比較,結(jié)果為小于或相等BHIBLS高于低于或相等無符號數(shù)比較,結(jié)果為高于無符號數(shù)比較,結(jié)果為低于或相等4.2.3ARM匯編語言編程的重點3.匯編語言子程序調(diào)用及返回(1)子程序的調(diào)用
在ARM匯編語言中,子程序調(diào)用是通過BL指令來完成的。BL指令的語法格式如下:
BLsubname
其中,subname是被調(diào)用的子程序的名稱。(2)子程序的返回
在返回調(diào)用子程序時,轉(zhuǎn)移鏈接指令保存到LR寄存器(R14)中的值需要拷貝回程序寄存器PC(R15)。4.2.3ARM匯編語言編程的重點子程序返回的方法(1)對于最簡單的子程序,一條MOV指令就可以完成子程序的返回。
SUB2……MOVPC,R14 ;把R14拷貝到R15來返回(2)對于在子程序中出現(xiàn)嵌套調(diào)用時,鏈接寄存器LR中的返回地址可能會在第二次調(diào)用時被覆蓋,
所以需要將返回地址壓入堆棧來進行保存。
SUB1STMFDR13!,{R0-R2,R14};保存工作寄存器和鏈接
BLSUB2……LDMFDR13!,{R0-R2,PC};恢復(fù)工作寄存器和鏈接4.2.3ARM匯編語言編程的重點3.匯編語言子程序調(diào)用及返回4.跳轉(zhuǎn)表思想在程序設(shè)計中,有時為使程序完成一定的功能,需要調(diào)用一系列子程序中的一個,而決定究竟調(diào)用哪一個由程序的計算值確定。跳轉(zhuǎn)表是解決該問題的有效方案。跳轉(zhuǎn)表是利用程序計數(shù)器PC在通用寄存器文件中的可見性來實現(xiàn)的。
BLJUMPTAB……JUMPTABADRR1,SUBTAB ;R1←SUBTABCMPR0,#SUBMAX ;檢查超限
LDRLSPC,[R1,R0,LSL#2] ;如果OK,則跳轉(zhuǎn)到表中
BERROR ;否則,發(fā)出錯誤信息SUBTABDCDSUB0 ;子程序表入口
DCDSUB1DCDSUB24.2.3ARM匯編語言編程的重點5.ARM與Thumb間的狀態(tài)轉(zhuǎn)換及函數(shù)的相調(diào)用(1)狀態(tài)切換的實現(xiàn)
ARM/Thumb之間的狀態(tài)切換是通過一條專用的轉(zhuǎn)移交換指令BX來實現(xiàn)的。BX利用Rn寄存器中目的地址值的最后一位來判斷跳轉(zhuǎn)后的狀態(tài)。當(dāng)最后一位為0時,表示轉(zhuǎn)移到ARM狀態(tài);當(dāng)最后一位為1時,表示轉(zhuǎn)移到Thumb狀態(tài)。BXRnBX{cond}Rn當(dāng)前狀態(tài)是Thumb時當(dāng)前狀態(tài)是ARM時310RnPCBX
ARM/Thumb選擇位:
0-ARM1-Thumb4.2.3ARM匯編語言編程的重點(2)ARM/Thumb之間的函數(shù)調(diào)用
在同一狀態(tài)下的子程序調(diào)用,通常只需要一條指令實現(xiàn)調(diào)用:
BLfunction
實現(xiàn)返回也只需要從LR恢復(fù)PC即可:
MOVPC,LR
在不同狀態(tài)下的子程序調(diào)用中,就需要進行狀態(tài)之間的切換,需要考慮到以下幾點:需要由BX來切換狀態(tài),因為BL不能完成狀態(tài)切換。需要在BX之前先保存好LR,BX不能自動保存返回地址到LR。需要用“BXLR”來返回,不能使用“MOVPC,LR”,返回時要仔細考慮保存在LR中最低位的內(nèi)容是否正確。4.2.3ARM匯編語言編程的重點5.ARM與Thumb間的狀態(tài)轉(zhuǎn)換及函數(shù)的相調(diào)用4.2.4ARM匯編程序?qū)嵗?.簡單的ARM指令程序
(1)在ADS編譯環(huán)境下
AREAARMex,COED,READONLY ;設(shè)置本段程序的名稱及屬性、
;代碼段的名稱為ARMex
ENTRY ;標(biāo)記要執(zhí)行的第一條指令
startMOVR0,#10 ;設(shè)置參數(shù)
MOVR1,#3ADDR0,R0,R1 ;R0=R0+R1
stopMOVR0,#&18 ;軟中斷參數(shù)設(shè)置
LDRR1,=&20026 ;軟中斷參數(shù)設(shè)置
SWI0x123456 ;將CPU的控制權(quán)交給調(diào)試器
END ;文件的結(jié)束標(biāo)尺1.簡單的ARM指令程序
(2)在GNU編譯環(huán)境下
.global_start.text /*標(biāo)志代碼段*/
_start:MOVR0,#10 /*設(shè)置參數(shù)*/
MOVR1,#3ADDR0,R0,R1 /*R0=R0+R1*/
stop:MOVR0,#&18 /*軟中斷參數(shù)設(shè)置*/
LDRR1,=&20026 /*軟中斷參數(shù)設(shè)置*/
SWI0x123456 /*將CPU的控制權(quán)交給調(diào)試器*/
.end /*文件的結(jié)束標(biāo)尺*/4.2.4ARM匯編程序?qū)嵗?.數(shù)據(jù)塊復(fù)制
.global_start/*定義全局標(biāo)號*/
.text/*定義該段為代碼段*/
.equNUM20/*設(shè)置將要復(fù)制的字數(shù)*/
_stratLDRR0,=src/*程序開始,R0寄存器指向源數(shù)據(jù)區(qū)src*/
LDRR1,=dst/*R1寄存器指向目標(biāo)數(shù)據(jù)區(qū)dst*/
MOVR2,#NUM/*R2指定將要復(fù)制的字數(shù)*/
MOVSP,#0x400/*設(shè)置數(shù)據(jù)棧指針,用于保存工作寄存器數(shù)值*/
BcopyMOVSR3,R2,LSR#3
/*需要進行的以8個字為單位的復(fù)制次數(shù)*/
BEQCword/*對于剩下不足8個字的數(shù)據(jù),跳轉(zhuǎn)到Cword*//*以字為單位復(fù)制*/
STMFDSP!,{R4-R11}/*保存工作寄存器*/
OcopyLDMIAR0!,{R4-R11}/*從源數(shù)據(jù)區(qū)讀8個字的數(shù)據(jù),放到8個寄存器中,*//*并更爩目標(biāo)數(shù)據(jù)區(qū)指針R0*/
STMIAR1!,{R4-R11}/*將這8個字數(shù)據(jù)寫入到目標(biāo)數(shù)據(jù)區(qū)中,*//*并更新目標(biāo)數(shù)據(jù)區(qū)指針R1*/
SUBSR3,R3,#1/*將塊復(fù)制次數(shù)減1*/
BNEOcopy/*循環(huán),直到完成以8個字為單位的塊復(fù)制*/
LTMFDSP!,{R4-R11}/*恢復(fù)工作寄存器值*/4.2.4ARM匯編程序?qū)嵗?.數(shù)據(jù)塊復(fù)制
CwordANDSR2,R2,#7/*剩下不足8個字的數(shù)據(jù)的字數(shù)*/
BEQStop/*數(shù)據(jù)復(fù)制完成*/
WcopyLDRR3,[R0],#4/*從源數(shù)據(jù)區(qū)讀1個字的數(shù)據(jù),放到R3寄存器中,*//*并更新目標(biāo)數(shù)據(jù)區(qū)指針R0*/
STRR3,[R1],#4/*將這R3中數(shù)據(jù)寫入到目標(biāo)數(shù)據(jù)區(qū)中,*//*并更新目標(biāo)數(shù)據(jù)區(qū)指針R1*/
SUBSR2,R2,#1/*將字數(shù)減1*/
BNEWcopy/*循環(huán),直到完成以字為單位的數(shù)據(jù)復(fù)制*/
Stop
/*程序結(jié)束處理*/
MOVR0,#0x18/*本條與下條指令的作用是參數(shù)傳遞*/
LDRR1,=0x20026
SWI0x123456/*將CPU的控制權(quán)交給調(diào)試器*/
.data/*定義數(shù)據(jù)段*/
.longsrc1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,1,2,3,4.longdst0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0/*這里的DCD定義源數(shù)據(jù)區(qū)src及目標(biāo)數(shù)據(jù)區(qū)dst*/
.end/*結(jié)束匯編*/4.2.4ARM匯編程序?qū)嵗?.利用跳轉(zhuǎn)表實現(xiàn)程序跳轉(zhuǎn)
.global_start/*定義全局標(biāo)號*/
.text/*定義該段為代碼段*/
.equNUM2
/*跳轉(zhuǎn)表中的子程序個數(shù)*/
_stratMOVR0,#0
/*設(shè)置3個參數(shù),R0選擇調(diào)用哪個子程序*/
MOVR1,#3
/*R1為子程序要用的參數(shù)*/
MOVR2,#2
/*R2為子程序要用的參數(shù)*/
BLFunc
/*調(diào)用子程序Func,進行算術(shù)運算*/
StopMOVR0,#0x18
/*本條與下條指令的作用是參數(shù)傳遞*/
LDRR1,=0x20026SWI0x123456/*并CPU的控制權(quán)交給調(diào)試器*/4.2.4ARM匯編程序?qū)嵗?.利用跳轉(zhuǎn)表實現(xiàn)程序跳轉(zhuǎn)
FuncCMPR0,#NUM/*判斷選擇R0是否在有效范圍之內(nèi)*/
MOVHSPC,LR/*如果超出范圍則程序返回*/
ADRR3,JTable/*讀取跳轉(zhuǎn)表的基地址*/
LDRPC,[R3,R0,LSL#2]
/*根據(jù)參數(shù)R0的值跳轉(zhuǎn)到相應(yīng)的子程序*/
JTable
/*定義跳轉(zhuǎn)表的首地址*/
.longDoAdd
/*當(dāng)參數(shù)R0為0時上面的代碼將選擇DoAdd*/
.longDoSub
/*當(dāng)參數(shù)R0為1時上面的代碼將選擇DoSub*/
DoAddADDR0,R1,R2
/*子程序DoAdd執(zhí)行加法操作*/
MOVPC,LR
/*子程序DoAdd返回*/
DoSubSUBR0,R1,R2
/*子程序DoSub執(zhí)行加法操作*/
MOVPC,LR
/*子程序DoSub返回*/
.end/*結(jié)束匯編*/4.2.4ARM匯編程序?qū)嵗?/p>
ADS編譯環(huán)境下的匯編代碼與GNU編譯環(huán)境下有較多不同點,主要是符號及偽操作的不同。ADS下的偽操作符GNU下的偽操作符ADS下的偽操作符GNU下的偽操作符INCLUDE.includeBUSWIDTHSETA16.equBUSWIDTH,16TCLK2EQUPB25.equTCLK2,PB25MACRO.macroEXPORT.globalMEND.endmIMPORT.externEND.endDCD.longAREAWord,COED,READONLY.textIF:DEF:.ifdefAREABlock,DATA,READWRITE.dataELSE.elseCODE32.arm或.CODE[32]ENDIF.endifCODE16.thumb或.CODE[16]:OR:|LTORG.ltorg:SHL<<%.fillRN.reqEntryEntry:GBLA.global4.2.4ARM匯編程序?qū)嵗?.3嵌入式C語言程序設(shè)計基礎(chǔ)1.C語言“預(yù)處理偽指令”在嵌入式程序設(shè)計中的應(yīng)用2.嵌入式程序設(shè)計中的函數(shù)及函數(shù)庫3.嵌入式程序設(shè)計中常用的C語言語句4.嵌入式程序設(shè)計中C語言的變量、數(shù)組、結(jié)構(gòu)、聯(lián)合4.3.1C語言“預(yù)處理偽指令”在嵌入式程序設(shè)計中的應(yīng)用
“預(yù)處理命令”可以改進程序設(shè)計的環(huán)境,提高編程效率,一般以#號打頭,可分為以下三種:(1)文件包含(2)宏定義(3)條件編譯1.文件包含
文件包含偽指令可將頭文件包含到程序中,頭文件中定義的內(nèi)容包括符號常量、復(fù)合變量原型、用戶定義的變量類型原型和函數(shù)的原型說明等。編譯器編譯預(yù)處理時用文件包含的正文內(nèi)容替換到實際程序中。
文件包含偽指令的格式:
#include<頭文件名.h>;標(biāo)準(zhǔn)頭文件
#include“頭文件名.h”;自定義頭文件
#include宏標(biāo)識符4.3.1C語言“預(yù)處理偽指令”在嵌入式程序設(shè)計中的應(yīng)用
2.宏定義
宏定義偽指令分為:簡單宏、參數(shù)宏、條件宏、預(yù)定義宏及宏釋放。
(1)簡單宏:#define宏標(biāo)識符宏體(2)參數(shù)宏:#define宏標(biāo)識符(形式參數(shù)表)宏體例:用帶參數(shù)宏進行數(shù)學(xué)運算。
定義帶參數(shù)的宏:
#defineSQR(x,y)sqrt((x)*(x)+(y)*(y))
源文件中有:
z=SQR(a+b,a-b);
替換后:
z=sqrt((a+b)*(a+b)+(a-b)*(a-b));4.3.1C語言“預(yù)處理偽指令”在嵌入式程序設(shè)計中的應(yīng)用
(3)條件宏定義
#ifdef
宏標(biāo)識符
#ifndef
宏標(biāo)識符
#undef
宏標(biāo)識符
#define宏標(biāo)識符
宏體
#define 宏標(biāo)識符
宏體
#else #else #undef
宏標(biāo)識符
#define 宏標(biāo)識符
宏體
#define宏標(biāo)識符
宏體
#endif
#endif
例:用條件宏實現(xiàn)塊大小的定義。
#ifdnefBLOCK_SIZE
#defineBLOCK_SIZE128#else
#undefBLOCK_SIZE#defineBLOCK_SIZE128#endif4.3.1C語言“預(yù)處理偽指令”在嵌入式程序設(shè)計中的應(yīng)用
2.宏定義3.條件編譯
條件編譯偽指令是寫給編譯器的,指示編譯器在滿足某一條件時僅編譯源文件中與之相應(yīng)的部分。其格式如右框中所示:
#if(條件表達式1)
…#elif(條件表達式2)
… #elif(條件表達式n) … #else …#endif4.3.1C語言“預(yù)處理偽指令”在嵌入式程序設(shè)計中的應(yīng)用
4.3.2嵌入式程序設(shè)計中的函數(shù)及函數(shù)庫
函數(shù)是C語言程序設(shè)計的核心。一個較大的C語言程序一般是由一個主函數(shù)和若干個子函數(shù)組成,每個函數(shù)完成一個特定的功能。函數(shù)之間也可以相互調(diào)用。1.函數(shù)的格式定義性說明格式:[存儲類說明符]類型說明符[修飾符]標(biāo)識符(參數(shù)表)
{函數(shù)體}原型說明格式:extern類型說明符[修飾符]標(biāo)識符(參數(shù)表){函數(shù)體}2.嵌入式程序設(shè)計中的函數(shù)及函數(shù)庫
函數(shù)庫是為了減少編程工作量,將一些常用的功能的函數(shù)放在函數(shù)庫中供公共使用。它包括
C
的標(biāo)準(zhǔn)庫函數(shù),也包括一些用戶自己編寫非標(biāo)準(zhǔn)庫。例如,44blib.h是根據(jù)基于S3C44B0X處理器的開發(fā)板及其功能模塊編寫的一個C語言函數(shù)庫。它不屬于C語言的標(biāo)準(zhǔn)庫。4.3.2嵌入式程序設(shè)計中的函數(shù)及函數(shù)庫4.3.3嵌入式程序設(shè)計中常用的C語言語句1.C語言語句格式為:
[標(biāo)號:]語句[;]
2.C語言語句很多,常用到的有以下幾種:
(1)條件語句
條件語句的格式:
兩重選擇:多重選擇:
if(條件表達式)if(條件表達式1)
語句1;語句1;
elseelseif(條件表達式2)
語句2;語句2;┆
elseif(條件表達式n)
語句n;2.C語言語句很多,常用到的有以下幾種:
(2)switch語句
switch語句的格式:
switch(){case常量表達式1:[語句1;]case常量表達式2:[語句2;]
┆case常量表達式n:[語句n;]default:[語句n+1;]}4.3.3嵌入式程序設(shè)計中常用的C語言語句2.C語言語句很多,常用到的有以下幾種:
(3)循環(huán)語句
循環(huán)語句的格式:
①for循環(huán)語句格式
for(表達式1;表達式2;表達式3)
語句;
②while循環(huán)語句格式
while(條件表達式)
語句;
③dowhile循環(huán)語句格式
do
語句;
while(條件表達式);4.3.3嵌入式程序設(shè)計中常用的C語言語句4.3.4嵌入式程序設(shè)計中C語言的變量、數(shù)組、結(jié)構(gòu)、聯(lián)合1.變量
[存儲類型]類型說明符[修飾符]標(biāo)識符[=初值][,標(biāo)識符[=初值]]…;2.數(shù)組
(1)一維數(shù)組
類型說明符
標(biāo)識符
[常量表達式][={初值,初值,…}];
char
標(biāo)識符[]=“字符串”;
(2)二維數(shù)組
類型說明符標(biāo)識符[m][n][={{初值表},{初值表}…}];
(3)指針數(shù)組和數(shù)組指針
類型說明符*標(biāo)志符
[常量表達式][={地址,地址,…}];
類型說明符(*標(biāo)志符)[][=數(shù)組標(biāo)識符];3.結(jié)構(gòu)說明
[存儲類說明符]
struct
[結(jié)構(gòu)原型名]
{
類型說明標(biāo)識符[,標(biāo)識符…];類型說明標(biāo)識符[,標(biāo)識符…];
…
}標(biāo)識符[={初值表}[,標(biāo)識符[={初值表}]…];
4.聯(lián)合說明
[存儲類說明符]union[聯(lián)合原型名]{類型說明符標(biāo)識符[,標(biāo)識符…];類型說明符標(biāo)識符[,標(biāo)識符…];
…
}標(biāo)識符={初值表}[,標(biāo)識符[={初值表}]…];4.3.4嵌入式程序設(shè)計中C語言的變量、數(shù)組、結(jié)構(gòu)、聯(lián)合4.4嵌入式C語言程序設(shè)計實例1.實驗箱測試程序?qū)嵗?.嵌入式C語言程序編寫的簡單構(gòu)架3.Flash測試代碼介紹4.4.1實驗箱的測試程序?qū)嵗?/p>
我們以實驗箱上的各個功能模塊的整個測試程序為例,介紹如何運用C語言進行基于ARM的嵌入式程序設(shè)計。該程序完成的功能如下所示:(1)實驗箱加電時數(shù)碼管八段全亮;
LED1、LED2輪流閃爍(頻率近1Hz);使用PC鍵盤操作;串口終端輸出信息表示聯(lián)機成功。(2)可能使用開發(fā)板上的PC鍵盤選擇各部分功能測試操作。程序源代碼介紹
整個測試程序主文件main.c的代碼構(gòu)成圖如圖所示,由BootLoader啟動程序進入C語言主函數(shù)main()入口。4.4.1實驗箱的測試程序?qū)嵗^文件BootLoadermain.c文件函數(shù)聲明,這里只聲明本文件中定義的函數(shù),其他用到的庫函數(shù)已在包含頭文件中聲明44blib.h44b.hrtc.h…/LCD_Text/bmp.hvoidmain(void)voiduser_input_action(intvalue)charUser_Getch(void)voidFuncTest_view(int
stdio)voidLCD_menu(void)各種類型的變量、數(shù)組定義char*info[][2]本文件中各個函數(shù)代碼的定義Voidmain(void)本文件主函數(shù),它又調(diào)用其他函數(shù),包括庫函數(shù)中的函數(shù)sys_init()Lcd_Init()Lcd_Clr()Lcd_Active_Clr()Lcd_Dma_Trans()Delay(100)init_keyboard()voiduser_input_action(intvalue)在本函數(shù)中,運用switch()語句根據(jù)不同的參數(shù)去調(diào)用不同的測試函數(shù)來完成不同的功能模塊測試TS_Test()Digit_Led_Test()Lcd_Test()Test_Keyboard()Test_Iis()Test_Timer()Dhcp_Test()Test_Flash()Test_Iic()Tftp_Test()charUser_Getch(void)voidFuncTest_view(int
stdio)voidLCD_menu(void)FuncTest_view(UART)4.4.2嵌入式C語言程序編寫的簡單構(gòu)架1.#include預(yù)編譯指令
個C語言代碼,一般要用#include編譯指令將所需要的頭文件加到該程序中,這是很有必要的,尤其是對編寫較大的程序代碼時。隨后是定義一些外部變量,并對程序中的函數(shù)進行聲明。2.主函數(shù)main()或_start()的編寫
在每一個C語言代碼中,一定要有一個主函數(shù)main()或_start(),在該函數(shù)中完成該程序文件所要完成的各個功能,一般是通過調(diào)用各個子函數(shù)來完成。當(dāng)然它也可以調(diào)用其他文件中的函數(shù)。3.完成相應(yīng)功能的各個功能函數(shù)的編寫
各個函數(shù)之間可以相互調(diào)用。4.4.3Flash測試代碼介紹下面給出功能測試程序中Flash測試程序的代碼結(jié)構(gòu)圖:包含頭文件int
Identify(int
base_addr)int
erase_flash(int
base_addr)int
erase_sector(int
base_addr)int
wait_flash_ready(intaddress,pB0SIZEdata各種類型的變量、數(shù)組定義voidTest_Flash(void)int
Program(int
addr_base,char*pData,int
data_size)int
erase_sector(int
base_addr)int
erase_flash(int
base_addr)int
wait_flash_ready(intaddress,pB0SIZEdata)int
Identify(int
base_addr)flash.h函數(shù)聲明各個函數(shù)代碼的定義flash.c文件4.5嵌入式C語言程序設(shè)計技巧1.變量定義2.參數(shù)傳遞3.循環(huán)條件4.5.1變量定義1.在變量聲明的時候,最好把所有相同類型的變量放在一起定義,這樣可以優(yōu)化存儲器布局。
例子:
chara;chara;shortb;charc;charc;shortb;
intd;intd;
在數(shù)據(jù)區(qū)里的布局:apadbpadcdacbdwordincADDa1,a1,#1shortincADDa1,a1,#1MOVa1,a1,LSL#16MOVa1,a1,ASR#16MOVPC,LRcharincADDa1,a1,#1ANDa1,a1,#&FFMOVPC,LR2.對于局部變量類型的定義,使用short或char來定義變量并不是總能節(jié)省存儲空間。有時使用32位int或unsinged
int局部變量更有效率一些。
不同類型局部變量的編譯結(jié)果:int
wordinc(inta){returna+1;}shortshortinc(shorta){returna+1;}charcharinc(chara){returna+1;}4.5.1變量定義3.變量定義中,為了精簡程序,程序員總是竭力避免使用冗余變量。但有時使用冗余變量可以減少存儲器訪問的次數(shù)這可以提高系統(tǒng)性能。4.5.1變量定義4.5.2參數(shù)傳遞
為了使單獨編譯的C語言程序和匯編程序能夠互相調(diào)用,定義了統(tǒng)一的函數(shù)過程調(diào)用標(biāo)準(zhǔn)ATPCS。ATPCS定義了寄存器組中的{R0~R3}作為參數(shù)傳遞和結(jié)果返回寄存器,如果參數(shù)數(shù)目超過四個,則使用堆棧進行傳遞。內(nèi)部寄存器的訪問速度是遠遠大于存儲器的,所以要盡量使參數(shù)傳遞在寄存器里面進行,即應(yīng)盡量把函數(shù)的參數(shù)控制在四個以下。4.5.3循環(huán)條件
計數(shù)循環(huán)是程序中十分常用的流程控制結(jié)構(gòu),一般有以下兩種形式:
for(loop=1;loop<=limit;loop++)
for(loop=limit;loop!=0;loop--)這兩種循環(huán)形式在邏輯上并沒有效率差異,但是映射到具體的體系結(jié)構(gòu)中時,就產(chǎn)生了很大的不同,如下圖所示。intfact1(intlimit){……
for(i=1;i<=limit;i++){fact=fact*i;}……}intfact2(intlimit){……
for(i=limit;i!=0;i--){fact=fact*i;}……}fact1……0x000010:MULR2,R1,R20x000014:ADD
R1,R1,#10x000018:CMPR1,R00x00001c:BLE0x000010……0x000024:MOVPC,LRfact2……0x000010:MULR0,R1,R00x000014:SUBS
R1,R1,#10x000018:BLE0x000010……4.5.3循環(huán)條件4.6C與匯編語言混合編程1.ATPCS介紹2.內(nèi)嵌匯編3.C和ARM匯編程序間相互調(diào)用4.6.1ATPCS介紹
ATPCS是ARM程序和Thumb程序中子程序調(diào)用的基本規(guī)則,目的是為了使單獨編譯的C語言程序和匯編程序之間能夠相互調(diào)用。這些基本規(guī)則包括子程序調(diào)用過程中寄存器的使用規(guī)則、數(shù)據(jù)棧的使用規(guī)則和參數(shù)的傳遞規(guī)則。
1.寄存器的使用規(guī)則寄存器別名特殊名使用規(guī)則R0a1
參數(shù)/結(jié)果/scratch寄存器1R1a2
參數(shù)/結(jié)果/scratch寄存器2R2a3
參數(shù)/結(jié)果/scratch寄存器3R3a4
參數(shù)/結(jié)果/scratch寄存器4R4v1
ARM狀態(tài)局部變量寄存器1R5v2
ARM狀態(tài)局部變量寄存器2R6v3
ARM狀態(tài)局部變量寄存器3R7v4wrARM狀態(tài)局部變量寄存器4Thumb狀態(tài)工作寄存器R8v5
ARM狀態(tài)局部變量寄存器5R9v6sbARM狀態(tài)局部變量寄存器6,在支持RWPI的ATPCS中為靜態(tài)基址寄存器R10v7slARM狀態(tài)局部變量寄存器7,在支持數(shù)據(jù)棧檢查的ATPCS中為數(shù)據(jù)棧限制指針R11v8fpARM狀態(tài)局部變量寄存器8/幀指針R12
ip子程序內(nèi)部調(diào)用的scratch寄存器R13
sp數(shù)據(jù)棧指針R14
lr連接寄存器R15
pc程序計數(shù)器4.6.1ATPCS介紹
(1)子程序間通過寄存器R0~R3來傳遞參數(shù),此時寄存器R0~R3可以記作A1~A4,被調(diào)用的子程序在返回前無需恢復(fù)寄存器R0-R3的內(nèi)容。(2)子程序中,使用寄存器R4~R11來保存局部變量,這時寄存器可以記作V1~V8。若
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 出租 包租 合同范本
- 企業(yè)服務(wù)顧問合同范例
- 剛配材料合同范例
- 農(nóng)村樓房安裝電梯合同范例
- 代播協(xié)議合同范例
- 出售二手車交易合同范例
- 農(nóng)資袋子銷售合同范例
- 兼職勞務(wù)合同范例飲品店
- 兼職派遣合同范例
- 凱倫股合同范例
- 云南省昆明市2025年中考語文模擬試卷六套【附參考答案】
- 新反詐知識考試題庫200題(含答案)
- 第22課《陳涉世家》課件(共71張)
- 2022年高考(全國甲卷)語文仿真模擬卷【含答案】
- _重大事故后果分析(精)
- 水泥攪拌樁施工監(jiān)理質(zhì)量控制要點
- 初級診斷師培訓(xùn)課程QC基礎(chǔ)知識
- 第7章 吸附課件
- 中醫(yī)醫(yī)院重癥醫(yī)學(xué)科建設(shè)與管理指南
- 注塑機臺生產(chǎn)日報表
- JGJ_T231-2021建筑施工承插型盤扣式鋼管腳手架安全技術(shù)標(biāo)準(zhǔn)(高清-最新版)
評論
0/150
提交評論