要做程序的優(yōu)化,最徹底的方法當(dāng)然是匯編!還有除了匯編以外(除了二進(jìn)制)能讓你對(duì)你的處理器有更全面的控制嗎?!對(duì)于ARM匯編,作為一個(gè)初學(xué)者,也就只好先補(bǔ)補(bǔ)基礎(chǔ)了@_@。
首先,程序段的定義從AREA 開始,它命名一個(gè)代碼區(qū)域,注意,用非阿拉伯?dāng)?shù)字作為名字時(shí),應(yīng)該用|把名字包起來,CODE關(guān)鍵字聲明程序(猜測(cè)),readonly聲明訪問權(quán)限(猜測(cè))。EXPORT 來表示某個(gè)可以用作外部連接的符號(hào)(簡(jiǎn)單點(diǎn),應(yīng)該就是函數(shù)名?)。END用來結(jié)尾。
#eg:
AREA |.text|, CODE, READONLY
EXPORT square
; int square(int i)
square ;armcc把不縮進(jìn)的正文作為一個(gè)標(biāo)號(hào)定義
MUL r1,r0,r0
MOV r0,r1 ;ARM乘法指令有一個(gè)限制,就是目標(biāo)寄存器不能和第一個(gè)參數(shù)寄存器相同
MOV pc,lr ;對(duì)Thumb指令,應(yīng)該改為BX lr
END
使用import,可以聲明其他文件中定義的標(biāo)號(hào),要用ARM C庫(kù)的話,就import |Lib$Request$armlib|, WEAK表示本行的標(biāo)號(hào)如果找不到,不會(huì)報(bào)告連接錯(cuò)誤。如果程序包含主程序main,那么要引入標(biāo)號(hào)__main,代表C庫(kù)初始化的開始。RN可以讓用戶給寄存器命名。
#eg:
AREA |.text|, CODE,READONLY
EXPORT main
IMPORT |Lib$$Request$$armlib|, WEAK
IMPORT __main ;C library entry
IMPORT printf ;prints to stdout
i RN 4
;int main(void)
main
STMFD sp!,{i,lr}
MOV i,#0
loop
ADR r0,print_string
MOV r1,i
MUL r2,i,i
BL printf
ADD i,i,#1
CMP i,#10
BLT loop
LDMFD sp!,{i,pc}
print_string
DCB " Square of d is d\n", 0
END
MAP(別名^)和FIELD(別名#),可以在堆棧中為變量和數(shù)組定義和分配空間。
MAP
0 ;map symbols to offsets
starting at offset 0?
a FIELD 4 ;a is 4 bytes integer(at offset 0)
b FIELD 2 ;b is bytes integer(at offset 4)
c FIELD 64 ;c is an array of 64 characters (at offset 6)
length FIELD 0 ;length records the current offset reached?
MACRO用來聲明宏:
MACRO
CHECKSUM $ alignment
checksum_$ alignment
LDR w,[data],#4
l0 ;loop
IF $ alignment<>0
ADD sum,sum,w,LSR #8, $alignement
LDR w,[data],#4
SUBS N,N,#1
ADD sum,sum,w,LSL#32-8* $ alignment
ELSE
ADD sum,sum,w
LDR w,[data],#4
SUBS N,N,#1
ENDIF
BGT BT l0
MOV pc,lr
MEND
針對(duì)匯編的優(yōu)化主要是面向硬件的。首先是流水線,有些load指令要需要多個(gè)周期來完成,可以通過調(diào)整指令的順序(當(dāng)然要保證邏輯)來改善性能。另外,盡量讓程序只是用寄存器,方法是搞清楚數(shù)據(jù)占用寄存器的時(shí)間關(guān)系,實(shí)現(xiàn)寄存器有效的分時(shí)復(fù)用。另外,可以將長(zhǎng)度較小的變量合并到一個(gè)32位寄存器中保存,以節(jié)省寄存器。由于PC可以通過程序操作,對(duì)于條件指令,可以直接用PC與形成分支的參數(shù)作運(yùn)算來尋找對(duì)應(yīng)的分支:
;int switch_relative(int x)
switch_relative
CMP x,#8
ADDLT pc,pc,x,LSL,#2
B method_d ;利用流水線,如果PC還是按順序那么default分支的預(yù)取址就不
;會(huì)被沖掉
B method_0
B method_1