ARM匯編部分:
A. 條件執行
CMP R0,#5
BEQ BYPASS
ADD R1,R1,R0
SUB R1,R1,R2
BYPASS ......
可以替代為:
CMP R0,#5
ADDNE R1,R1,R0
SUBNE R1,R1,R2
......
如果被跳過的指令序列并不進行復雜的操作,使用條件執行都要比使用轉移好,因為ARM轉義指令一般要用3個周期來執行。
對于以下的條件執行可以這樣來寫匯編:
; if ( (a = = b) && (c = = d) ) e++
CMP R0,R1
CMPEQ R2,R3
ADDEQ R4,R4,#1
C語言部分:
A. 很多人認為以下兩種變量定義空間效率一樣的:
① char a;
short b;
char c;
int d;
② char a;
char b;
short c;
int d;
其實不然,定義次序的不同導致終映像中不同的數據布局,實際中第二種定義方式能夠節約更多的存儲空間,所以在變量聲名時,把所有相同類型的變量放在一起定義,這樣可以優化存儲器布局。
B. 我們總是設法使用short或者char來定義變量,認為這樣能夠節省存儲空間,但也有例外,我們先來看下這幾段C代碼及其相應的匯編:
① C代碼:
int addition(int a)
{ return a+1; }
匯編:
ADD a1,a1,#1
② C代碼:
short addition(short a)
{ return a+1; }
匯編:
ADD a1,a1,#1
MOV a1,a1,LSL #16
MOV a1,a1,ASR #16
MOV PC,LR
③ C代碼:
char addition(char a)
{ return a+1; }
匯編:
ADD a1,a1,#1
AND a1,a1,# &FF
MOV PC,LR
因為char 類型、short類型分別是8位、16位,完成加法操作后,需要在32位的寄存器中進行符號擴展,所以使用32位的int以及unsinged int做加法效率。
C.冗余變量要消耗空間,許多人都不贊同使用它,但是下面這種情況就不同了。
int m ( void );
Int n ( void );
Int fg;
① void func_1 ( void )
{
fg += m ( );
fg += n ( );
}
② void func_2 ( void )
{
int tmp = fg;
tmp += m ( );
tmp += n ( );
fg = tmp;
}
在func_1 ( ) 中每次對全局變量fg的加法操作都需要從存儲器load到寄存器里,加完數據后還要store回原來的存儲器,所以這個函數就進行了兩次load和兩次store操作。在func_2 ( ) 中,tmp作為局部變量,系統為其分配一寄存器,首先執行一次load操作后,由tmp進行加法,只需一次store操作把結果送給fg,節省了很多時間,畢竟讀/寫存儲器的時間耗費要比讀/寫寄存器高得多。
D.關于計數循環的問題,一般我們都會使用累加計數的方式,遞減計數用得比較少,雖然從C代碼上看累加和遞減兩種方式時間復雜度相同,但是在對時間要求嚴格的嵌入式領域,這兩者執行時間還是有差別的。
① 累加計數方式:
for ( i = 1; i < times; i ++ )
{
tmp = tmp * i ;
}
匯編:
……
0x06: MUL R2,R1,R2
0x10: ADD R1,R1,#1
0x14: CMP R2,R0
0x18: BLE 0x06
……
② 遞減計數方式:
for ( i = times; i > 1; i -- )
{
tmp = tmp * i ;
}
匯編:
……
0x06: MUL R0,R1,R0
0x10: SUB R1,R1,#1
0x14: BNE 0x06
……
從上面的匯編可以看出,累加計數需要用到專門的CMP指令來判斷條件,而遞減計數只需要利用條件執行的NE進行判別,當循環次數的量很大的話時間效率就有差別了。
嵌入式中C和匯編的一些技巧
更新時間: 2008-08-27 14:05:38來源: 粵嵌教育瀏覽量:1155