| 導購 | 订阅 | 在线投稿
分享
 
 
 

C語言嵌入系統編程修煉-性能優化

來源:互聯網  2008-06-01 02:03:13  評論

使用宏定義

在C語言中,宏是産生內嵌代碼的唯一方法。對于嵌入式系統而言,爲了能達到性能要求,宏是一種很好的代替函數的方法。

寫一個"標准"宏MIN ,這個宏輸入兩個參數並返回較小的一個:

錯誤做法:

#define MIN(A,B) ( A <= B ? A : B )

正確做法:

#define MIN(A,B) ((A)<= (B) ? (A) : (B) )

對于宏,我們需要知道三點:

(1)宏定義"像"函數;

(2)宏定義不是函數,因而需要括上所有"參數";

(3)宏定義可能産生副作用。

下面的代碼:

least = MIN(*p++, b);

將被替換爲:

( (*p++) <= (b) ?(*p++):(b) )

發生的事情無法預料。

因而不要給宏定義傳入有副作用的"參數"。

C語言嵌入系統編程修煉-性能優化
更多內容請看C/C++進階技術文檔 java編程開發手冊 系統安全設置專題,或 使用寄存器變量

當對一個變量頻繁被讀寫時,需要反複訪問內存,從而花費大量的存取時間。爲此,C語言提供了一種變量,即寄存器變量。這種變量存放在CPU的寄存器中,使用時,不需要訪問內存,而直接從寄存器中讀寫,從而提高效率。寄存器變量的說明符是register。

對于循環次數較多的循環控制變量及循環體內反複使用的變量均可定義爲寄存器變量,而循環計數是應用寄存器變量的最好候選者。

(1) 只有局部自動變量和形參才可以定義爲寄存器變量。因爲寄存器變量屬于動態存儲方式,凡需要采用靜態存儲方式的量都不能定義爲寄存器變量,包括:模塊間全局變量、模塊內全局變量、局部static變量;

(2) register是一個"建議"型要害字,意指程序建議該變量放在寄存器中,但最終該變量可能因爲條件不滿足並未成爲寄存器變量,而是被放在了存儲器中,但編譯器中並不報錯(在C++語言中有另一個"建議"型要害字:inline)。

下面是一個采用寄存器變量的例子:

/* 求1+2+3+….+n的值 */

Word Addition(BYTE n)

{

register i,s=0;

for(i=1;i<=n;i++)

{

s=s+i;

}

return s;

}

本程序循環n次,i和s都被頻繁使用,因此可定義爲寄存器變量。

C語言嵌入系統編程修煉-性能優化
更多內容請看C/C++進階技術文檔 Java編程開發手冊 系統安全設置專題,或 內嵌彙編

程序中對時間要求苛刻的部分可以用內嵌彙編來重寫,以帶來速度上的顯著提高。但是,開發和測試彙編代碼是一件辛勞的工作,它將花費更長的時間,因而要慎重選擇要用彙編的部分。

在程序中,存在一個80-20原則,即20%的程序消耗了80%的運行時間,因而我們要改進效率,最主要是考慮改進那20%的代碼。

嵌入式C程序中主要使用在線彙編,即在C程序中直接插入_asm{ }內嵌彙編語句:

/* 把兩個輸入參數的值相加,結果存放到另外一個全局變量中 */

int result;

void Add(long a, long *b)

{

_asm

{

MOV AX, a

MOV BX, b

ADD AX, [BX]

MOV result, AX

}

}


C語言嵌入系統編程修煉-性能優化
更多內容請看C/C++進階技術文檔 Java編程開發手冊 系統安全設置專題,或 利用硬件特性

首先要明白CPU對各種存儲器的訪問速度,基本上是:

CPU內部RAM>外部同步RAM>外部異步RAM>Flash/ROM

對于程序代碼,已經被燒錄在FLASH或ROM中,我們可以讓CPU直接從其中讀取代碼執行,但通常這不是一個好辦法,我們最好在系統啓動後將FLASH或ROM中的目標代碼拷貝入RAM中後再執行以提高取指令速度;

對于UART等設備,其內部有一定容量的接收BUFFER,我們應盡量在BUFFER被占滿後再向CPU提出中斷。例如計算機終端在向目標機通過RS-232傳遞數據時,不宜設置UART只接收到一個BYTE就向CPU提中斷,從而無謂浪費中斷處理時間;

假如對某設備能采取DMA方式讀取,就采用DMA讀取,DMA讀取方式在讀取目標中包含的存儲信息較大時效率較高,其數據傳輸的基本單位是塊,而所傳輸的數據是從設備直接送入內存的(或者相反)。DMA方式較之中斷驅動方式,減少了CPU 對外設的幹預,進一步提高了CPU與外設的並行操作程度。

C語言嵌入系統編程修煉-性能優化
更多內容請看C/C++進階技術文檔 Java編程開發手冊 系統安全設置專題,或 活用位操作

使用C語言的位操作可以減少除法和取模的運算。在計算機程序中數據的位是可以操作的最小數據單位,理論上可以用"位運算"來完成所有的運算和操作,因而,靈活的位操作可以有效地提高程序運行的效率。舉例如下:

/* 方法1 */

int i,j;

i = 879 / 16;

j = 562 % 32;

/* 方法2 */

int i,j;

i = 879 >> 4;

j = 562 - (562 >> 5 << 5);

對于以2的指數次方爲"*"、"/"或"%"因子的數學運算,轉化爲移位運算"<< >>"通常可以提高算法效率。因爲乘除運算指令周期通常比移位運算大。

C語言位運算除了可以提高運算效率外,在嵌入式系統的編程中,它的另一個最典型的應用,而且十分廣泛地正在被使用著的是位間的與(&)、或()、非(~)操作,這跟嵌入式系統的編程特點有很大關系。我們通常要對硬件寄存器進行位設置,譬如,我們通過將AM186ER型80186處理器的中斷屏蔽控制寄存器的第低6位設置爲0(開中斷2),最通用的做法是:

#define INT_I2_MASK 0x0040

wTemp = inword(INT_MASK);

outword(INT_MASK, wTemp &~INT_I2_MASK);

而將該位設置爲1的做法是:

#define INT_I2_MASK 0x0040

wTemp = inword(INT_MASK);

outword(INT_MASK, wTemp INT_I2_MASK);

判定該位是否爲1的做法是:

#define INT_I2_MASK 0x0040

wTemp = inword(INT_MASK);

if(wTemp & INT_I2_MASK)

{

… /* 該位爲1 */

}

上述方法在嵌入式系統的編程中是非經常見的,我們需要牢固把握。

C語言嵌入系統編程修煉-性能優化
更多內容請看C/C++進階技術文檔 Java編程開發手冊 系統安全設置專題,或 總結

在性能優化方面永遠注重80-20預備,不要優化程序中開銷不大的那80%,這是勞而無功的。

宏定義是C語言中實現類似函數功能而又不具函數調用和返回開銷的較好方法,但宏在本質上不是函數,因而要防止宏展開後出現不可預料的結果,對宏的定義和使用要慎而處之。很遺憾,標准C至今沒有包括C++中inline函數的功能,inline函數兼具無調用開銷和安全的優點。

使用寄存器變量、內嵌彙編和活用位操作也是提高程序效率的有效方法。

除了編程上的技巧外,爲提高系統的運行效率,我們通常也需要最大可能地利用各種硬件設備自身的特點來減小其運轉開銷,例如減小中斷次數、利用DMA傳輸方式等。

C語言嵌入系統編程修煉-性能優化
更多內容請看C/C++進階技術文檔 Java編程開發手冊 系統安全設置專題,或

使用宏定義   在C語言中,宏是産生內嵌代碼的唯一方法。對于嵌入式系統而言,爲了能達到性能要求,宏是一種很好的代替函數的方法。   寫一個"標准"宏MIN ,這個宏輸入兩個參數並返回較小的一個:   錯誤做法:      #define MIN(A,B)  ( A <= B ? A : B )   正確做法:      #define MIN(A,B) ((A)<= (B) ? (A) : (B) )   對于宏,我們需要知道三點:   (1)宏定義"像"函數;   (2)宏定義不是函數,因而需要括上所有"參數";   (3)宏定義可能産生副作用。   下面的代碼:      least = MIN(*p++, b);   將被替換爲:      ( (*p++) <= (b) ?(*p++):(b) )   發生的事情無法預料。   因而不要給宏定義傳入有副作用的"參數"。 [url=/bbs/detail_1785253.html][img]http://image.wangchao.net.cn/it/1323424128897.gif[/img][/url] 更多內容請看C/C++進階技術文檔 java編程開發手冊 系統安全設置專題,或 使用寄存器變量   當對一個變量頻繁被讀寫時,需要反複訪問內存,從而花費大量的存取時間。爲此,C語言提供了一種變量,即寄存器變量。這種變量存放在CPU的寄存器中,使用時,不需要訪問內存,而直接從寄存器中讀寫,從而提高效率。寄存器變量的說明符是register。 對于循環次數較多的循環控制變量及循環體內反複使用的變量均可定義爲寄存器變量,而循環計數是應用寄存器變量的最好候選者。   (1) 只有局部自動變量和形參才可以定義爲寄存器變量。因爲寄存器變量屬于動態存儲方式,凡需要采用靜態存儲方式的量都不能定義爲寄存器變量,包括:模塊間全局變量、模塊內全局變量、局部static變量;   (2) register是一個"建議"型要害字,意指程序建議該變量放在寄存器中,但最終該變量可能因爲條件不滿足並未成爲寄存器變量,而是被放在了存儲器中,但編譯器中並不報錯(在C++語言中有另一個"建議"型要害字:inline)。   下面是一個采用寄存器變量的例子:      /* 求1+2+3+….+n的值 */   Word Addition(BYTE n)   {    register i,s=0;    for(i=1;i<=n;i++)    {     s=s+i;    }    return s;   }   本程序循環n次,i和s都被頻繁使用,因此可定義爲寄存器變量。 [url=/bbs/detail_1785253.html][img]http://image.wangchao.net.cn/it/1323424128934.gif[/img][/url] 更多內容請看C/C++進階技術文檔 Java編程開發手冊 系統安全設置專題,或 內嵌彙編   程序中對時間要求苛刻的部分可以用內嵌彙編來重寫,以帶來速度上的顯著提高。但是,開發和測試彙編代碼是一件辛勞的工作,它將花費更長的時間,因而要慎重選擇要用彙編的部分。   在程序中,存在一個80-20原則,即20%的程序消耗了80%的運行時間,因而我們要改進效率,最主要是考慮改進那20%的代碼。   嵌入式C程序中主要使用在線彙編,即在C程序中直接插入_asm{ }內嵌彙編語句:      /* 把兩個輸入參數的值相加,結果存放到另外一個全局變量中 */   int result;   void Add(long a, long *b)   {    _asm    {     MOV AX, a     MOV BX, b     ADD AX, [BX]     MOV result, AX    }   }    [url=/bbs/detail_1785253.html][img]http://image.wangchao.net.cn/it/1323424128952.gif[/img][/url] 更多內容請看C/C++進階技術文檔 Java編程開發手冊 系統安全設置專題,或 利用硬件特性   首先要明白CPU對各種存儲器的訪問速度,基本上是:      CPU內部RAM > 外部同步RAM > 外部異步RAM > Flash/ROM   對于程序代碼,已經被燒錄在FLASH或ROM中,我們可以讓CPU直接從其中讀取代碼執行,但通常這不是一個好辦法,我們最好在系統啓動後將FLASH或ROM中的目標代碼拷貝入RAM中後再執行以提高取指令速度;   對于UART等設備,其內部有一定容量的接收BUFFER,我們應盡量在BUFFER被占滿後再向CPU提出中斷。例如計算機終端在向目標機通過RS-232傳遞數據時,不宜設置UART只接收到一個BYTE就向CPU提中斷,從而無謂浪費中斷處理時間;   假如對某設備能采取DMA方式讀取,就采用DMA讀取,DMA讀取方式在讀取目標中包含的存儲信息較大時效率較高,其數據傳輸的基本單位是塊,而所傳輸的數據是從設備直接送入內存的(或者相反)。DMA方式較之中斷驅動方式,減少了CPU 對外設的幹預,進一步提高了CPU與外設的並行操作程度。 [url=/bbs/detail_1785253.html][img]http://image.wangchao.net.cn/it/1323424128965.gif[/img][/url] 更多內容請看C/C++進階技術文檔 Java編程開發手冊 系統安全設置專題,或 活用位操作   使用C語言的位操作可以減少除法和取模的運算。在計算機程序中數據的位是可以操作的最小數據單位,理論上可以用"位運算"來完成所有的運算和操作,因而,靈活的位操作可以有效地提高程序運行的效率。舉例如下:      /* 方法1 */   int i,j;   i = 879 / 16;   j = 562 % 32;   /* 方法2 */   int i,j;   i = 879 >> 4;   j = 562 - (562 >> 5 << 5);   對于以2的指數次方爲"*"、"/"或"%"因子的數學運算,轉化爲移位運算"<< >>"通常可以提高算法效率。因爲乘除運算指令周期通常比移位運算大。   C語言位運算除了可以提高運算效率外,在嵌入式系統的編程中,它的另一個最典型的應用,而且十分廣泛地正在被使用著的是位間的與(&)、或( )、非(~)操作,這跟嵌入式系統的編程特點有很大關系。我們通常要對硬件寄存器進行位設置,譬如,我們通過將AM186ER型80186處理器的中斷屏蔽控制寄存器的第低6位設置爲0(開中斷2),最通用的做法是:   #define INT_I2_MASK 0x0040   wTemp = inword(INT_MASK);   outword(INT_MASK, wTemp &~INT_I2_MASK);   而將該位設置爲1的做法是:      #define INT_I2_MASK 0x0040   wTemp = inword(INT_MASK);   outword(INT_MASK, wTemp   INT_I2_MASK);   判定該位是否爲1的做法是:      #define INT_I2_MASK 0x0040   wTemp = inword(INT_MASK);   if(wTemp & INT_I2_MASK)   {   … /* 該位爲1 */   }   上述方法在嵌入式系統的編程中是非經常見的,我們需要牢固把握。 [url=/bbs/detail_1785253.html][img]http://image.wangchao.net.cn/it/1323424128986.gif[/img][/url] 更多內容請看C/C++進階技術文檔 Java編程開發手冊 系統安全設置專題,或 總結   在性能優化方面永遠注重80-20預備,不要優化程序中開銷不大的那80%,這是勞而無功的。   宏定義是C語言中實現類似函數功能而又不具函數調用和返回開銷的較好方法,但宏在本質上不是函數,因而要防止宏展開後出現不可預料的結果,對宏的定義和使用要慎而處之。很遺憾,標准C至今沒有包括C++中inline函數的功能,inline函數兼具無調用開銷和安全的優點。   使用寄存器變量、內嵌彙編和活用位操作也是提高程序效率的有效方法。   除了編程上的技巧外,爲提高系統的運行效率,我們通常也需要最大可能地利用各種硬件設備自身的特點來減小其運轉開銷,例如減小中斷次數、利用DMA傳輸方式等。 [url=/bbs/detail_1785253.html][img]http://image.wangchao.net.cn/it/1323424129014.gif[/img][/url] 更多內容請看C/C++進階技術文檔 Java編程開發手冊 系統安全設置專題,或
󰈣󰈤
王朝萬家燈火計劃
期待原創作者加盟
 
 
 
>>返回首頁<<
 
 
 
 
 熱帖排行
 
 
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有