MDK中One ELF Section per Function選項功能探究

whalefall發表於2018-04-26

本文主要探討的是MDK開發工具中One ELF Section per Function選項對於程式碼優化的作用及其實現的機制。

這裡以EK-STM32F開發板的LCDDemo實驗例程為例進行說明:

1)在MDK的Project -> Options for Target -> Target選項卡下,在Code Generation 中選中Use MicroLIB,選擇使用微庫。在User選項卡Run User Programs After Build/Rebuild中,勾選Run #1,同時在文字框中輸入命令C:/Keil/ARM/BIN31/fromelf.exe --bin -o  ./output/LCDDemo.bin ./output/

LCDDemo_MDK.axf用於生成.bin檔案。

    2)在選項卡C/C++中選擇優化等級2,同時不選中任何的優化選項。儲存,編譯連結,下載執行程式,檢視output中LCDDemo.bin檔案的大小為4728Byte。

3)在圖3所示的介面中,將One ELF Section per Function選項選中,儲存,編譯連結,下載執行程式,檢視output中LCDDemo.bin檔案的大小為3700Byte。

可以從以上的操作看出, 在其他條件相同的情況下,選項One ELF Section per Function可以將LCDDemo最後生成的.bin檔案的大小減少1028Byte,這對於儲存資源有限的嵌入式裝置來說,還是具有很大的吸引力的。

那麼,選項One ELF Section per Function是如何對C程式程式碼進行優化呢?為此,筆者特別設計了一個方案用於驗證選項One ELF Section per Function的優化功能。

首先在LCDDemo工程的main.c檔案中加入如下的程式碼:

void unuse()

{

int i,j = 0;

for (i=0; i<0xfffff; i++) j++;

for (j=0; j<0xfffff; j++) i++;

}

unuse()函式僅是為了測試用而加入的一個函式,該函式為被其他任何的函式所呼叫。下面分別檢視使用選項One ELF Section per Function和不使用選項One ELF Section per Function的區別。

A,              如之前的步驟2)所示操作,生成的LCDDemo.bin的大小為7396Byte。同時,筆者採用反彙編過程進一步驗證,找到了unuse()的反彙編程式碼。可以看出,確實因為新增了unuse()這個函式,而使得最後生成的LCDDemo.bin檔案的變大。.

B,              如之前的步驟3)所示操作,生成的LCDDemo.bin的大小為3700Byte。同時,筆者採用反彙編過程進一步驗證,未找到unuse()的反彙編程式碼。可以看出,使用選項. One ELF Section per Function後,即使新增了未使用的函式unuse(),也對於最後生成的LCDDemo.bin檔案沒有任何的影響。

因此,可以得出,選項One ELF Section per Function的主要功能是對冗餘函式的優化。通過這個選項,可以在最後生成的二進位制檔案中將冗餘函式排除掉(雖然其所在的檔案已經參與了編譯連結),以便最大程度地優化最後生成的二進位制程式碼。

而該選項實現的機制是將每一個函式作為一個優化的單元,而並非整個檔案作為參與優化的單元。

選項One ELF Section per Function所具有的這種優化功能特別重要,尤其是在對於生成的二進位制檔案大小有嚴格要求的場合。人們習慣將一系列介面函式放在一個檔案裡,然後將其整個包含在工程中,即使這個檔案將只有一個函式被用到。這樣,最後生成的二進位制檔案中就有可能包含眾多的冗餘函式,造成了寶貴儲存空間的浪費。

選項One ELF Section per Function對於一個大工程的優化效果尤其突出,有時候甚至可以達到減半的效果。當然,對於小工程或是少有冗餘函式的工程來說,其優化效果就沒有那麼明顯了。

相關文章