要做程序的優化,最徹底的方法當然是匯編!還有除了匯編以外(除了二進制)能讓你對你的處理器有更全面的控制嗎?!對于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,#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(別名#),可以在堆棧中為變量和數組定義和分配空間。
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
針對匯編的優化主要是面向硬件的。首先是流水線,有些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