要做程式的最佳化,最徹底的方法當然是彙編!還有除了彙編以外(除了二進位)能讓你對你的處理器有更全面的控制嗎?!對於ARM彙編,作為一個初學者,也就只好先補補基礎了@_@。
首先,程式段的定義從AREA 開始,它命名一個代碼地區,注意,用非阿拉伯數字作為名字時,應該用|把名字包起來,CODE關鍵字聲明程式(猜測),readonly聲明存取權限(猜測)。EXPORT 來表示某個可以用作外部串連的符號(簡單點,應該就是函數名?)。END用來結尾。#eg: AREA |.text|, CODE, READONLY EXPORT square ; int square(int i) square ;armcc把不縮排的本文作為一個標號定義 MUL r1,r0,r0 MOV r0,r1 ;ARM乘法指令有一個限制,就是目標寄存器不能和第一個參數寄存器相同 MOV pc,lr ;對Thumb指令,應該改為BX lr END 使用import,可以聲明其他檔案中定義的標號,要用ARM C庫的話,就import |Lib$Request$armlib|, WEAK表示本行的標號如果找不到,不會報告串連錯誤。如果程式包含主程式main,那麼要引入標號__main,代表C庫初始化的開始。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,#0loop 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(別名#),可以在堆棧中為變數和數組定義和分配空間。 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 $ alignmentchecksum_$ alignment LDR w,[data],#4l0 ;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 針對彙編的最佳化主要是面向硬體的。首先是流水線,有些load指令要需要多個周期來完成,可以通過調整指令的順序(當然要保證邏輯)來改善效能。另外,盡量讓程式只是用寄存器,方法是搞清楚資料佔用寄存器的時間關係,實現寄存器有效分時複用。另外,可以將長度較小的變數合并到一個32位寄存器中儲存,以節省寄存器。由於PC可以通過程式操作,對於條件指令,可以直接用PC與形成分支的參數作運算來尋找對應的分支: ;int switch_relative(int x)switch_relative CMP x,#8 ADDLT pc,pc,x,LSL,#2 B method_d ;利用流水線,如果PC還是按順序那麼default分支的預取址就不 ;會被衝掉 B method_0 B method_1