摘要:該文從基于8051核的MCU結構特征出發,結合C語言自身特點,給出若干高效C程序設計的技巧。實踐證明,在C程序設計中依據8051的功能特性對源代碼進行優化,能大幅度提高最終程序的執行效率。
關鍵詞:MCU;結構特征;程序設計;技巧
中圖分類號:TP393文獻標識碼:A文章編號:1009-3044(2009)32-8943-03
Efficient C Language Programming Skills
CHAI Shou-li1, GAO Liang2
(1.Shandong Yingcai University of Computer Science, Ji'nan 250104, China; 2.Anhui University of Computer Science, Hefei 230039, China)
Abstract: This paper from the 8051 core MCU based on structural features, combined features of C language itself is given a number of highly efficient C programming skills. Practice has proved that, in the C program design features based on 8051 to optimize the source code, can greatly improve the efficiency of the final implementation of the procedures.
Key words: MCU; structural features; programming; skills
C語言憑借自身的結構化設計思想和對底層的數據的強大處理能力逐漸成為嵌入式開發的主流語言。雖然目前大部分C集成開發工具都具有優化能力,而且優化的結果有時比使用匯編語言編寫的程序效果還好,然而,這些優化工作大部分是針對程序和算法本身的優化,而針對MCU體系結構的進行的優化很少或者幾乎沒有,本文就是針對這個問題,給出幾種解決方法。
1 巧妙地利用寄存器變量
使用寄存器變量可以提升程序運行的速度,節約程序運行的時間,因為CPU對寄存器的尋址時間是最短的,可以在一個機器周期內完成。
假設有語句for(i=0;i<10;i++);對變量i的位置的不同申明將會得到不同的結果。
在keil c中作如下定義
unsigned char i;編譯產生的匯編語言如下:
CLR A
MOV R7,A
LOOP:INC R7
CJNER7,#0x0A,LOOP
unsigned char idata i;編譯產生的匯編語言如下:
CLR A
MOVR0,#0x08
MOV @R0,A
LOOP:MOV RO,#0x08
INC @R0
MOVA,@RO
CJNEA,#0x0A,LOOP
unsigned char xdata i;編譯產生的匯編語言如下:
CLRA
MOVDPTR,#0x0000
MOVX@DPTR,A
LOOP:MOV DPTR,#0x0000
MOVXA,@DPTR
INC A
MOVX@DPTR,A
MOVXA,@DPTR
CJNEA,#0x0A,LOOP
通用寄存器可用于傳送和暫存數據,也可參與算術邏輯運算,并保存運算結果。通過上述分析,可以看見,當編譯器將變量i作為寄存器(R7)變量處理的時候,產生的目標代碼最小,且可以在一個機器周期內尋址。程序員必須熟悉每個寄存器的一般用途和特殊用途,只有這樣,才能在程序中做到正確、合理地使用它們。
但是,由于基于8051核的MCU資源有限,寄存器顯得極其寶貴,所以,寄存器變量通常被定義為局部頻繁使用的操作,如上例,在一個子函數中操作完了即可被銷毀,或者系統頻繁使用的全局變量,對其他情況要盡量避免使用。讀者在使用的時候可以仔細查閱編譯器說明手冊。
2 利用移位實現快速乘除操作
大部分MCU都選配一個輔助處理器,該處理器主要完成對數據進行邏輯與、或、非、循環、移位等基本操作,人們將之稱為布爾處理功能。巧妙的利用移位寄存器可以實現快速的乘除運算。設有如下代碼:
unsigned char mul,div,x,y;//申明變量
mul = x*3;//x乘以3賦值給mul
div = y/3;//y除以3賦值給div
匯編產生的目標代碼為:
MOV A,0x0A
MOVB,#0x03
MULAB
MOV0x80,A
MOVA,0x0B
MOVB,#0x03
DIV AB
MOV0x09,A
如果將上述程序語句改成等價效果的語句:
mul = x<<1;//x乘以2賦值給mul
div = y>>1;//y除以2賦值給div
MOVA,0x0A
ADDA,ACC
MOV0x08,A
MOVA,0x0B
CLRC
RRCA
MOV0x09,A
可以看出,使用移位操作產生的目標代碼明顯優于使用乘除產生的目標代碼,而且MUL和DIV指令的周期比ADD指令周期長。
如果將上述方法變通一下,對于日常生活中的十進制計算方法遷移到二進制計算方法,利用計算百分比的閥值,利用假設需要計算統計的結果百分比大于80%,可以計算出新的統計閥值為80×128/100≈102。這樣就可以用移位元算代替乘除運算。
3 巧妙利用51核的位尋址功能
嵌入式系統是嵌入在一個大系統中執行著特殊任務的專用計算機系統,所以大部分MCU都具有特殊的指令處理能力,8051CPU可以對部分特殊功能寄存器和字節地址20H~2FH進行位尋址。
如有下述代碼,程序中需要經常對變量x的最低位和次低位的值進行01判斷,可以寫代碼如下:
unsignedchar bdata x,y;
y = x 0x01;//獲知最低位情況
x = x>>1;
y = x 0x01;//獲知次低位情況
匯編產生的結果如下:
MOV A,0x20
JZJ1
MOVR7,#0x01
SJMPJ2
J1:MOVR7,#0x00
J2:MOV0x21,R7
MOVA,0x20
CLRC
RRCA
MOV0x20,A
JZJ3
MOVR7,0x01
SJMPJ4
J3:MOVR7,#0x00
J4:MOV0x21,R7
如果采用位操作則上述代碼只要寫成,該段代碼由于采用了位尋址,所以在程序中任何其他位置,如果在變量x發生改變的情況下,再次獲知最低位和次低位01情況,就不需要再次執行上述程序的計算工作,直接使用即可。
unsigned char bdatax;
bit y0,y1;
sbitr0 = x^0;
sbitr1 = x^1;
y0 = r0;
y1 = r1;
匯編產生的目標代碼:
MOVC,0x20.0
MOV0x21.0,C
MOVC,0x20.1
MOV0X21.1,C
4 結束語
本文結合基于8051核的MCU的內部結構特征,給出了若干C高效編程的技巧,本文的思想也可以應用到其他類型的MCU中去。筆者利用上述方法對一個1000多行C源代碼進行優化,編程產生的結果將原5K多的目標代碼降低為不足3K的目標代碼,幾乎減低了一半。
參考文獻:
[1] LinDen P V D. C程序設計奧秘[M].昆明:云南科技出版社,1998.
[2] Kamal R. 嵌入式系統體系結構、編程與設計[M].北京:清華大學出版社,2000.