天天看點

Keil C51編譯/連結/優化

Keil C51編譯/連結/優化

一、C51編譯庫及代碼優化技術

如下圖所示:可以根據優化等級的需要選擇相應的庫檔案。

Keil C51編譯/連結/優化

通過Keil ->Target 下 Memory Model / code Rom size 來進行配置

Keil C51編譯/連結/優化
SMALL:所有變量都被定義在8051單片機的片内RAM中,對這種變量的通路速度最快。
另外,堆棧也必須位于片内RAM中,而堆棧的長度是很重要的,實際棧長取決與不同函
數的嵌套深度。采用SMALL編譯模式與定義變量時指定data存儲器類型具有相同效果。

COMPACT:所有變量被定義在分頁尋址的片外XRAM中,每一頁片外XRAM的長度為256位元組:
即所有變量存儲在片外XRAM的某一頁中。這時對變量的通路是通過寄存器間接尋址
(MOVX @R0,MOVX @R1)進行的,變量的低8位位址由R0和R1确定,變量的高8位位址由P2口确定。
采用這種模式時,必須适當改變配置檔案STARTUP.A51中的參數:PDATASTART和PDATALEN;
同時還必須對uVision2的“Options選項/BL51 Locator 标簽頁/Pdata框”中鍵入合适的位址參數,
以確定P2口能輸出所需要的高8位位址。
采用COMPACT編譯模式與定義變量時指定pdata存儲器類型具有相同效果。

LARGE:所有變量被定義在片外XRAM中(最大可達64KB),使用資料指針DPTR來間接通路變量
(MOVX @DPTR),這種編譯模式對資料通路的效率最低,而且将增加程式的代碼長度。
采用LARGE編譯模式與定義變量時指定xdata存儲器類型具有相同效果。
           

1.1 代碼優化

C51可将即使有經驗的程式員編制的代碼進行優化,總共有9個優化級,C51的所有優化方法如下:

0級(Constan folding)的優化包括:

a、常數折疊:隻要有可能,編譯器就執行将表達式化為常數數字的計算,其中包括運作位址的計算。b、 簡單通路優化:對8051系統的内部資料和位位址進行通路優化。c、 跳轉優化:編譯器總是将跳轉延至最終目标上,是以跳轉到跳轉之間的指令被删除。

Keil C51編譯/連結/優化

1級(Dead code elimination)的優化包括:

a、 死碼消除:無用的代碼段被消除。b、 跳轉否決:根據一個測試回溯,條件跳轉被仔細檢查,以決定是否能夠簡化或删除。

Keil C51編譯/連結/優化

2級(Data overlaying)的優化包括:

a、資料覆寫:适于靜态覆寫的資料和位段被鑒别并标記出來。連接配接定位器BL51通過對全局資料流的分析,選擇可靜态覆寫的段。

Keil C51編譯/連結/優化

3級(Peephole optimization)的優化包括:

a、“窺孔”優化:将備援的MOV指令去掉,包括不必要的從存儲器裝入對象及裝入常數的操作。另外如果能節省存儲空間或者程式執行時間,複雜操作将由簡單操作所代替。

Keil C51編譯/連結/優化

4級(Register variables)的優化包括:

a、寄存器變量:使自動變量和函數參數盡可能位于工作寄存器中,隻要有可能,将不為這些變量保留資料存儲器空間。b、擴充通路優化:來自IDATA、XDATA、PDATA和CODE區域的變量直接包含在操作之中,是以大多數時候沒有必要将其裝入中間寄存器。c、局部公共子式消除:如果表達式中有一個重複執行的計算,第一次計算的結果被儲存,隻要有可能,将被用作後續的計算,是以可從代碼中消除繁雜的計算。d、CASE/SWITCH語句優化:将CASE/SWITCH語句作為跳轉表或跳轉串優化。

Keil C51編譯/連結/優化

5級(Common subexpression elimination)的優化包括:

a、全局公共子式消除:隻要有可能,函數内部相同的子表達式隻計算一次。中間結果存入一個寄存器以代替新的計算。b、簡單循環優化:以常量占據一段記憶體的循環再運作時被優化。

Keil C51編譯/連結/優化

6級(Loop rotation)的優化包括:

a、回路循環:如果程式代碼能更快更有效地執行,程式回路将進行循環。

Keil C51編譯/連結/優化

7級(Extended Index Access optimizing)的優化包括:

a、擴充入口優化:在适合時對寄存器變量使用DPTR資料指針,指針和數組通路被優化以減小程式代碼和提高執行速度。

Keil C51編譯/連結/優化

8級(Reuse Common Entry Code)的優化包括:

a、公共尾部合并:對同一個函數有多處調用時,一些設定代碼可被重複使用,進而減小程式代碼長度。

Keil C51編譯/連結/優化

9級(Common Block Subroutines)的優化包括:

a、公共子程式塊:檢測重複使用的指令序列,并将它們轉換為子程式。C51甚至會重新安排代碼以獲得更多的重複使用指令序列。

Keil C51編譯/連結/優化

二、C51與ASM混合程式設計技術

2.1 混合程式設計意義

通常用C51來編寫主程式。然而,在一些時序要求嚴格的采用彙程式設計式設計具有更高的效率,是以要求在C程式中調用一些用彙編語言編寫的子程式。

方法一、直接在函數體内的每個彙編語句前加?“asm”預編譯指。

void Test1(void)
{
    asm    MOV R1,#0AH
    asm    LOOP: INC A
    asm    DJNZ R0,LOOP
    return;
} 
           

方法二、把asm作為關鍵字後續彙編用大括号括起來

void Test2(void)
{
    asm
    {
        MOV R1,#0AH
        LOOP: INC A
        DJNZ R0,LOOP
    }
    return;
}
           

方法三、在C子產品内通過語句“#pragma”嵌入彙編代碼

void Test3 (void)
{
    #pragma asm
        MOV R1,#0AH
        LOOP: INC A
        DJNZ R0,LOOP
    #pragma endasm
    return;
}
           

三、C51中常見符号的命名規則

Keil C51編譯/連結/優化

3.1、C51函數名與彙程式設計式名的轉換規則

C51程式子產品編譯成目标檔案後,其中的函數名依據其定義的性質不同會轉換為不同的函數名,是以在C51和彙程式設計式的互相調用時要求彙程式設計式必須服從這種函數名的轉換規則。

Keil C51編譯/連結/優化

3.2、C51函數及其相關段的命名規則

一個C51源程式子產品被編譯後,其中的每一個函數以“?PR?函數名?子產品名”為名的命名規則被配置設定到一個獨立的CODE段。

注意:如果添加了“OVERLAYABLE”标志,故可被L51連接配接/定位器作覆寫分析

Keil C51編譯/連結/優化

四、C51函數的參數傳遞規則

參數的傳遞通過内部的R1-R7 來實作,最多可以傳遞三個參數。

Keil C51編譯/連結/優化

具體使用如下:

Keil C51編譯/連結/優化

五、 Data Overlay

大多數C編譯器函數參數和局部變量存儲在硬體棧的一部分稱為堆棧幀。這種方式好處是速度快, 對于棧空間大的架構來說很實用。

但是,8051 棧空間隻有256byte, 這種方式顯然不合适,太浪費8051的棧空間。

是以,C51的 C編譯器使用LX51連結器将函數參數和局部變量存儲在固定的記憶體位置(fix memory)使用定義明确的名稱(以便函數參數易于傳遞和通路)。

LX51連結器通過分析程式的結構,建立一個Call-tree, 使本地變量和函數參數放置在可覆寫的資料段中。這種技術非常好用,可以提供和傳統的堆棧幀相同通路的效果。

Keil C51編譯/連結/優化

Call Tree 結構圖:

Keil C51編譯/連結/優化