目前單片機的編程中,C51語言可以說是十分盛行,這種語言我也用過,但基本上都是用匯編語言.
C51語言的好處是可讀性強、移植性好、浮點運算,除此之外沒有別的好處了.我們不妨將兩種語言作一個比較:
1、效率方面:我曾對編譯后的C51語言分析過,可以發(fā)現(xiàn)由它生成的代碼數(shù)量,至少是匯編語言的兩倍以上,有的甚至高達十倍以上.占用空間大了,效率自然低.
2、移植性:C51的可移植性是比匯編好一些,但是單片機程序不同于微機控件程序那樣通用,幾乎沒有一個程序是可以到處移植的.單片機中最常用的移植程序大概就是運算子程序了,在這方面,匯編格式的運算子程序移植起來一個也不比C51遜色.
3、浮點運算:以我的感覺,單片機不適合采用浮點運算,我曾經(jīng)做過試驗,編譯了一個1.2+2.3的浮點運算,編譯后代碼長達2K多,完成這個運算所需要的時間就不用說了.我從八四年就開始研究單片機,到現(xiàn)在做過的系統(tǒng)中,含有單片機的超過五十項,所有系統(tǒng)中的運算,全部都采用定點運算,幾個定點子程序成了法寶,代碼效率非常高,請看下面的一段:
;W = W130 * (130 / Dia) * (130 / Dia) = W130 * 16900 / (Dia * Dia)
CalAndMem: MOV R5, SetPie130War1H
MOV R4, SetPie130War1L
MOV R3, #HIGH 16900
MOV R2, #LOW 16900
CALL QKMUL ;W130 * 16900
;雙字節(jié)乘法子程QKMUL
;(R3、R2)*(R5、R4)=R7、R6、R5、R4
;R3、R5、R7為高字節(jié)
MOV A, SetDiamt
MOV B, A
MUL AB
MOV R3, B
MOV R2, A
CALL NDIV ; /(Dia * Dia)
;二進制除法子程:NDIV
;入口:R7654=被除數(shù),R7高字節(jié),R32=除數(shù),R3高字節(jié)
;出口:R76=余數(shù),R7高字節(jié),R54=商,R5高字節(jié)
;R765432用于參數(shù)傳遞,不用保護
MOV SetPieWar1H, R5 ;當前缸徑下的壓力報警點
MOV SetPieWar1L, R4
--------
其中的子程序都是網(wǎng)上的成品,非常精簡.
4、實時性:用匯編編程序的人都知道,單片機的實時性要求很高,經(jīng)常需要計算這段程序需要多長時間,什么時間來中斷,中斷后執(zhí)行多長時間,對原程序有沒有妨礙,等等,這都是C51程序難以做到的.
5、節(jié)省內(nèi)存:當然,這和代碼效率是成反比的,同樣的內(nèi)存所能完成的功能也就大大提高.
永遠記住:高性能的代碼是用匯編語言編寫出來的,而不是用高級語言生成的,高質(zhì)量的PCB是有經(jīng)驗的工程技術人員用手工排出來的,而不是軟件自動布線出來的.
談談我對C51語言的看法
全部回復(21)
正序查看
倒序查看
使用C51可以寫出跟asm51毫不遜色的程序,這要看編程者的水平了,看下面的例子:
// ============================================================
// 功能:計算斜率
// 說明:被除數(shù)必須小于除數(shù),返回(n1*256)/n2的商
// 編程:臧德運
unsigned char Div(unsigned char n1, unsigned char n2)
{
union {unsigned int w; struct {unsigned char h, l;}bytes;}i;
unsigned char n;
if(n1==0){return(0);} // 被除數(shù)等于零返回
i.bytes.h=n1; i.bytes.l=0; // 使用公用體變量便于字節(jié)操作
for(n=8;n>0;n--)
{
i.w=i.w<<1;
if(CY==0)
{
if(ACC }
else ACC=ACC-n2;
i.bytes.h=ACC; i.bytes.l++;
}
return(i.bytes.l);
}
// ============================================================
// 功能:畫直線
// 編程:臧德運
void PLine(unsigned char x1, unsigned char y1, unsigned char x2, unsigned char y2, bit mode)
{
unsigned char n, k;
unsigned char x, y, x0, y0;
// 修正坐標原點為左下角
y1=y1^0x7f;
y2=y2^0x7f;
// 求X坐標偏移量的絕對值
if(x2 {
ACC=~ACC;ACC++; // 求絕對值
n=x1; x1=x2; x2=n; n=y1; y1=y2; y2=n; // 校正畫線方向提高效率
}
x0=ACC;
// 求Y坐標偏移量的絕對值
// 避免使用ABS函數(shù)提高效率
if(y2 y0=ACC;
x=x1; y=y1;
if(x0==y0) // 斜率等于1時畫正斜線
{
for(n=x0;n>0;n--)
{
Pixel(x, y, mode); x++;
if(y2>y1)y++;
else y--;
}
}
else
{
if(x0>y0) // 小于45度的斜線
{
k=Div(y0,x0);
for(n=0;n<=x0;n++)
{
ACC=k;B=n;ACC=ACC*B; y0=B;
if(ACC_7)y0++;
if(y2>y1){y=y1+y0;}else{y=y1-y0;}
Pixel(x1+n, y, mode);x++;
}
}
else // 大于45度的斜線
{
k=Div(x0,y0);
for(n=0;n<=y0;n++)
{
ACC=k;B=n;ACC=ACC*B;
if(ACC_7)B++;
x=B+x1;
Pixel(x, y, mode);if(y2>y1){y++;}else{y--;}
}
}
}
return;
}
// ============================================================
// 二(十六)進制轉(zhuǎn)換為十進制
// 返回:低四位十進制編碼+B(萬位)
// 格式:C51
// 編程:臧德運
unsigned int bin2dec(unsigned char bl, unsigned char bh)
{
union{unsigned int i; struct{unsigned char h, l;}bytes;}d;
d.bytes.l=bl; d.bytes.h=bh;
B=0;bh=0;
// 逐次d.i-10000,不夠減退出循環(huán),循環(huán)次數(shù)就是萬位值
while(1)
{
d.i+=0xd8f0;if(!CY)break;
B++;
}
d.i+=10000;
// 把減10000的余數(shù)轉(zhuǎn)化為100進制
// bh=100進制高位
// d.bytes.l=余數(shù),也就是100進制低位
for(bl=8;bl!=0;bl--)
{
bh+=bh; // 100進制高位同步左移
d.i=d.i<<1; // 8次位移逐次求100進位
if(d.bytes.h>=100) // 編譯器在編譯d.bytes.h>=100時,會有減100操作.
{
d.bytes.h=ACC; // 比較時刻運算結(jié)果送100進制低位
bh++; // 100進制進位
}
}
bl=B; // 保護B內(nèi)容
// 100進制轉(zhuǎn)換為10進制
d.bytes.l=(d.bytes.h/10)<<4;
d.bytes.l=d.bytes.l|B;
d.bytes.h=(bh/10)<<4;
d.bytes.h=d.bytes.h|B;
B=bl; // 恢復B內(nèi)容
return(d.i);
}
// ============================================================
// 功能:計算斜率
// 說明:被除數(shù)必須小于除數(shù),返回(n1*256)/n2的商
// 編程:臧德運
unsigned char Div(unsigned char n1, unsigned char n2)
{
union {unsigned int w; struct {unsigned char h, l;}bytes;}i;
unsigned char n;
if(n1==0){return(0);} // 被除數(shù)等于零返回
i.bytes.h=n1; i.bytes.l=0; // 使用公用體變量便于字節(jié)操作
for(n=8;n>0;n--)
{
i.w=i.w<<1;
if(CY==0)
{
if(ACC
else ACC=ACC-n2;
i.bytes.h=ACC; i.bytes.l++;
}
return(i.bytes.l);
}
// ============================================================
// 功能:畫直線
// 編程:臧德運
void PLine(unsigned char x1, unsigned char y1, unsigned char x2, unsigned char y2, bit mode)
{
unsigned char n, k;
unsigned char x, y, x0, y0;
// 修正坐標原點為左下角
y1=y1^0x7f;
y2=y2^0x7f;
// 求X坐標偏移量的絕對值
if(x2
ACC=~ACC;ACC++; // 求絕對值
n=x1; x1=x2; x2=n; n=y1; y1=y2; y2=n; // 校正畫線方向提高效率
}
x0=ACC;
// 求Y坐標偏移量的絕對值
// 避免使用ABS函數(shù)提高效率
if(y2
x=x1; y=y1;
if(x0==y0) // 斜率等于1時畫正斜線
{
for(n=x0;n>0;n--)
{
Pixel(x, y, mode); x++;
if(y2>y1)y++;
else y--;
}
}
else
{
if(x0>y0) // 小于45度的斜線
{
k=Div(y0,x0);
for(n=0;n<=x0;n++)
{
ACC=k;B=n;ACC=ACC*B; y0=B;
if(ACC_7)y0++;
if(y2>y1){y=y1+y0;}else{y=y1-y0;}
Pixel(x1+n, y, mode);x++;
}
}
else // 大于45度的斜線
{
k=Div(x0,y0);
for(n=0;n<=y0;n++)
{
ACC=k;B=n;ACC=ACC*B;
if(ACC_7)B++;
x=B+x1;
Pixel(x, y, mode);if(y2>y1){y++;}else{y--;}
}
}
}
return;
}
// ============================================================
// 二(十六)進制轉(zhuǎn)換為十進制
// 返回:低四位十進制編碼+B(萬位)
// 格式:C51
// 編程:臧德運
unsigned int bin2dec(unsigned char bl, unsigned char bh)
{
union{unsigned int i; struct{unsigned char h, l;}bytes;}d;
d.bytes.l=bl; d.bytes.h=bh;
B=0;bh=0;
// 逐次d.i-10000,不夠減退出循環(huán),循環(huán)次數(shù)就是萬位值
while(1)
{
d.i+=0xd8f0;if(!CY)break;
B++;
}
d.i+=10000;
// 把減10000的余數(shù)轉(zhuǎn)化為100進制
// bh=100進制高位
// d.bytes.l=余數(shù),也就是100進制低位
for(bl=8;bl!=0;bl--)
{
bh+=bh; // 100進制高位同步左移
d.i=d.i<<1; // 8次位移逐次求100進位
if(d.bytes.h>=100) // 編譯器在編譯d.bytes.h>=100時,會有減100操作.
{
d.bytes.h=ACC; // 比較時刻運算結(jié)果送100進制低位
bh++; // 100進制進位
}
}
bl=B; // 保護B內(nèi)容
// 100進制轉(zhuǎn)換為10進制
d.bytes.l=(d.bytes.h/10)<<4;
d.bytes.l=d.bytes.l|B;
d.bytes.h=(bh/10)<<4;
d.bytes.h=d.bytes.h|B;
B=bl; // 恢復B內(nèi)容
return(d.i);
}
0
回復
我想來到這里的人,大多數(shù)都是這方面的高手,上面有這么多人發(fā)表了自己的看法,不管怎么說,真正的是非我想大家都有數(shù).
有人感覺還是用C編寫單片機程序精煉,效率也不低,甚至和匯編語言差不多.
是,用高級語言編寫的程序看上去是很精簡,當然這也是個優(yōu)點,源程序上看不出什么問題來,但不知道他分析過編譯軟件生成的代碼沒有,有一個事實,在我們用手工編寫的程序中,Ri寄存器都當成工作寄存器來使用,可是用高級語言生成的程序中,他們都成了輔助寄存器,或者說是局部變量,一個很簡單的功能,本來利用幾個寄存器和幾條指令本地就可以處理,編譯器會把有關參數(shù)裝入Ri,然后調(diào)用相應的子程序,這些數(shù)據(jù)在Ri中的頻繁裝載,對整個程序的效率有什么樣的影響,大家一想就會明白.
有的人,說起話來他就不負責任,還想拿什么車來壓我,甚至舉出ARM單片機來說明問題,大家知道這種單片機是一種什么樣的器件啊,它是帶有流水線結(jié)構的32位機,有的甚至帶有協(xié)處理器,如果程序執(zhí)行狀遇到錯誤,系統(tǒng)會立即轉(zhuǎn)入異常狀態(tài),性能直追80486.請問這些功能是最普通、最常見的哪種單片機具備的?他還不如告訴我們不能直接用匯編語言編寫windows呢.
我的意思并不是否認用高級語言編寫軟件,我對C/VB用的都很熟練,很清楚高級語言的優(yōu)點,對于高檔高速器件,不應該局限于匯編上,但是對于絕大多數(shù)的使用環(huán)境,普通低檔單片機是足夠勝任的.是否采用高檔單片機,這不光是一個器件價格的問題,器件技術是否容易掌握也是一個不可忽視的因素.對于大多數(shù)工作人員使用最多的常規(guī)器件,采用匯編語言,可以最大限度的發(fā)揮器件的性能,不論是速度還是程序空間,都是高級語言無法相比的.我想這一點是誰也不能否認的.
有人感覺還是用C編寫單片機程序精煉,效率也不低,甚至和匯編語言差不多.
是,用高級語言編寫的程序看上去是很精簡,當然這也是個優(yōu)點,源程序上看不出什么問題來,但不知道他分析過編譯軟件生成的代碼沒有,有一個事實,在我們用手工編寫的程序中,Ri寄存器都當成工作寄存器來使用,可是用高級語言生成的程序中,他們都成了輔助寄存器,或者說是局部變量,一個很簡單的功能,本來利用幾個寄存器和幾條指令本地就可以處理,編譯器會把有關參數(shù)裝入Ri,然后調(diào)用相應的子程序,這些數(shù)據(jù)在Ri中的頻繁裝載,對整個程序的效率有什么樣的影響,大家一想就會明白.
有的人,說起話來他就不負責任,還想拿什么車來壓我,甚至舉出ARM單片機來說明問題,大家知道這種單片機是一種什么樣的器件啊,它是帶有流水線結(jié)構的32位機,有的甚至帶有協(xié)處理器,如果程序執(zhí)行狀遇到錯誤,系統(tǒng)會立即轉(zhuǎn)入異常狀態(tài),性能直追80486.請問這些功能是最普通、最常見的哪種單片機具備的?他還不如告訴我們不能直接用匯編語言編寫windows呢.
我的意思并不是否認用高級語言編寫軟件,我對C/VB用的都很熟練,很清楚高級語言的優(yōu)點,對于高檔高速器件,不應該局限于匯編上,但是對于絕大多數(shù)的使用環(huán)境,普通低檔單片機是足夠勝任的.是否采用高檔單片機,這不光是一個器件價格的問題,器件技術是否容易掌握也是一個不可忽視的因素.對于大多數(shù)工作人員使用最多的常規(guī)器件,采用匯編語言,可以最大限度的發(fā)揮器件的性能,不論是速度還是程序空間,都是高級語言無法相比的.我想這一點是誰也不能否認的.
0
回復
@deyun
使用C51可以寫出跟asm51毫不遜色的程序,這要看編程者的水平了,看下面的例子://============================================================//功能:計算斜率//說明:被除數(shù)必須小于除數(shù),返回(n1*256)/n2的商//編程:臧德運unsignedcharDiv(unsignedcharn1,unsignedcharn2){union{unsignedintw;struct{unsignedcharh,l;}bytes;}i;unsignedcharn;if(n1==0){return(0);} //被除數(shù)等于零返回i.bytes.h=n1;i.bytes.l=0; //使用公用體變量便于字節(jié)操作for(n=8;n>0;n--){ i.w=i.w
結(jié)構體用的不錯.
0
回復
@sdjufeng
我想來到這里的人,大多數(shù)都是這方面的高手,上面有這么多人發(fā)表了自己的看法,不管怎么說,真正的是非我想大家都有數(shù).有人感覺還是用C編寫單片機程序精煉,效率也不低,甚至和匯編語言差不多.是,用高級語言編寫的程序看上去是很精簡,當然這也是個優(yōu)點,源程序上看不出什么問題來,但不知道他分析過編譯軟件生成的代碼沒有,有一個事實,在我們用手工編寫的程序中,Ri寄存器都當成工作寄存器來使用,可是用高級語言生成的程序中,他們都成了輔助寄存器,或者說是局部變量,一個很簡單的功能,本來利用幾個寄存器和幾條指令本地就可以處理,編譯器會把有關參數(shù)裝入Ri,然后調(diào)用相應的子程序,這些數(shù)據(jù)在Ri中的頻繁裝載,對整個程序的效率有什么樣的影響,大家一想就會明白.有的人,說起話來他就不負責任,還想拿什么車來壓我,甚至舉出ARM單片機來說明問題,大家知道這種單片機是一種什么樣的器件啊,它是帶有流水線結(jié)構的32位機,有的甚至帶有協(xié)處理器,如果程序執(zhí)行狀遇到錯誤,系統(tǒng)會立即轉(zhuǎn)入異常狀態(tài),性能直追80486.請問這些功能是最普通、最常見的哪種單片機具備的?他還不如告訴我們不能直接用匯編語言編寫windows呢.我的意思并不是否認用高級語言編寫軟件,我對C/VB用的都很熟練,很清楚高級語言的優(yōu)點,對于高檔高速器件,不應該局限于匯編上,但是對于絕大多數(shù)的使用環(huán)境,普通低檔單片機是足夠勝任的.是否采用高檔單片機,這不光是一個器件價格的問題,器件技術是否容易掌握也是一個不可忽視的因素.對于大多數(shù)工作人員使用最多的常規(guī)器件,采用匯編語言,可以最大限度的發(fā)揮器件的性能,不論是速度還是程序空間,都是高級語言無法相比的.我想這一點是誰也不能否認的.
是的,匯編語言的優(yōu)點是代碼簡練,C的優(yōu)點是變量跟結(jié)構清晰.
使用高級語言完全能知道編譯器生成的代碼方法,甚至能直接利用Ri寄存器,還甚至人為的不使用R寄存器傳遞變量,看下面的例子:
// =================================================
// 寫數(shù)據(jù)到SPROM數(shù)據(jù)線
// 返回: ACK狀態(tài)
// 編程: 臧德運
bit w24XX(unsigned char c)
{
ACC=c; // 參數(shù)傳遞給A寄存器提高代碼效率
for(c=8;c>0;c--) // DJNZ R7, xxxx作循環(huán)提高效率
{
SDA24XX=0x80 & ACC; // 讓編譯器使用循環(huán)左移實現(xiàn)數(shù)據(jù)高位送SDA?
SCK24XX=1; _nop_(); // 插入控操作使高脈沖持續(xù)一段時間
SCK24XX=0; _nop_();
} // 這里是DJNZ R7, xxxx代碼
SDA24XX=1; _nop_();
SCK24XX=1; CY=SDA24XX;
_nop_(); SCK24XX=0;
Sdelay();
return(CY);
}
建議C和ASM混合使用.
使用高級語言完全能知道編譯器生成的代碼方法,甚至能直接利用Ri寄存器,還甚至人為的不使用R寄存器傳遞變量,看下面的例子:
// =================================================
// 寫數(shù)據(jù)到SPROM數(shù)據(jù)線
// 返回: ACK狀態(tài)
// 編程: 臧德運
bit w24XX(unsigned char c)
{
ACC=c; // 參數(shù)傳遞給A寄存器提高代碼效率
for(c=8;c>0;c--) // DJNZ R7, xxxx作循環(huán)提高效率
{
SDA24XX=0x80 & ACC; // 讓編譯器使用循環(huán)左移實現(xiàn)數(shù)據(jù)高位送SDA?
SCK24XX=1; _nop_(); // 插入控操作使高脈沖持續(xù)一段時間
SCK24XX=0; _nop_();
} // 這里是DJNZ R7, xxxx代碼
SDA24XX=1; _nop_();
SCK24XX=1; CY=SDA24XX;
_nop_(); SCK24XX=0;
Sdelay();
return(CY);
}
建議C和ASM混合使用.
0
回復
看了這么多,說C好或者匯編好時應該有個基調(diào).那就是需要我們的設計的系統(tǒng).有的系統(tǒng)資源充足,實時性要求又不高,用C寫好讀易懂,何樂而不為?有的系統(tǒng)要求效率高,需要用匯編,也很好.其實匯編和C的優(yōu)勢劣勢都顯而易見.一個3000行的C語言程序,你若硬要用匯編寫,也是可以的,不過打印出來只怕就是一本書了,而且如果過三個月誰讓你改改軟件怕也是個難事,汗啊~!但是無論你C用的多好,要與匯編比效率,總也是比不過的.感覺現(xiàn)在特別需要效率的地方也不是太多的,我比較喜歡的是大部分用C,特別需要效率的地方就嵌部分匯編進去.正所謂:60分萬歲,多一分浪費,凡事夠用就好,達到系統(tǒng)設計要求就是王道!!!
0
回復
說句老實話,我覺得您沒有體現(xiàn)出一個20余年單片機經(jīng)歷的工程師應有的見地.hotpower的話大體合乎情理您卻聽不進去,令人遺憾.
我想問一下,您做過的50幾個含有MCU的項目中,性能最佳的是什么型號?項目中程序代碼量最大的共計多少行?使用過RTOS嗎?含有TCP/IP棧嗎?語言之爭在缺乏應用背景的條件下是毫無意義的.網(wǎng)上爭論Java與C++,VC和Delphi的也是屢見不鮮,甚至有人好Java惡C,簡直是關公戰(zhàn)秦瓊,為什么國人總是樂于爭論這些不是問題的問題呢?C語言和匯編語言本不是一個層次,您的匯編子程序雖好,不過是在51匯編上可以調(diào)用罷了,其他架構的呢?我想是需要全盤改寫吧.C編譯器正是C高層次抽象和底層匯編的轉(zhuǎn)換接口.如果還一味沉浸在51系列的匯編之中,我覺得您再無進步的可能.如果您看過開放源代碼的操作系統(tǒng)如uC/OSII會有更深的體會,如果您對編譯原理有了解也不會從您所用的C51編譯器的代碼效率來得出一些不正確的觀點.
以上觀點,就事論事,不當之處,請指教.
我想問一下,您做過的50幾個含有MCU的項目中,性能最佳的是什么型號?項目中程序代碼量最大的共計多少行?使用過RTOS嗎?含有TCP/IP棧嗎?語言之爭在缺乏應用背景的條件下是毫無意義的.網(wǎng)上爭論Java與C++,VC和Delphi的也是屢見不鮮,甚至有人好Java惡C,簡直是關公戰(zhàn)秦瓊,為什么國人總是樂于爭論這些不是問題的問題呢?C語言和匯編語言本不是一個層次,您的匯編子程序雖好,不過是在51匯編上可以調(diào)用罷了,其他架構的呢?我想是需要全盤改寫吧.C編譯器正是C高層次抽象和底層匯編的轉(zhuǎn)換接口.如果還一味沉浸在51系列的匯編之中,我覺得您再無進步的可能.如果您看過開放源代碼的操作系統(tǒng)如uC/OSII會有更深的體會,如果您對編譯原理有了解也不會從您所用的C51編譯器的代碼效率來得出一些不正確的觀點.
以上觀點,就事論事,不當之處,請指教.
0
回復
@whatcall
說句老實話,我覺得您沒有體現(xiàn)出一個20余年單片機經(jīng)歷的工程師應有的見地.hotpower的話大體合乎情理您卻聽不進去,令人遺憾.我想問一下,您做過的50幾個含有MCU的項目中,性能最佳的是什么型號?項目中程序代碼量最大的共計多少行?使用過RTOS嗎?含有TCP/IP棧嗎?語言之爭在缺乏應用背景的條件下是毫無意義的.網(wǎng)上爭論Java與C++,VC和Delphi的也是屢見不鮮,甚至有人好Java惡C,簡直是關公戰(zhàn)秦瓊,為什么國人總是樂于爭論這些不是問題的問題呢?C語言和匯編語言本不是一個層次,您的匯編子程序雖好,不過是在51匯編上可以調(diào)用罷了,其他架構的呢?我想是需要全盤改寫吧.C編譯器正是C高層次抽象和底層匯編的轉(zhuǎn)換接口.如果還一味沉浸在51系列的匯編之中,我覺得您再無進步的可能.如果您看過開放源代碼的操作系統(tǒng)如uC/OSII會有更深的體會,如果您對編譯原理有了解也不會從您所用的C51編譯器的代碼效率來得出一些不正確的觀點.以上觀點,就事論事,不當之處,請指教.
謝謝,關于你說的問題,我基本是贊同的.
討論匯編與c的問題,確實不可能得出一個絕對的結(jié)論,這一點我在工作中也感覺到了.不可否認,C程序,按照大路性的編寫方式,其效率確實是個問題,但是對于超大的程序,匯編也是難以支持的.
我最近的一個項目,用的c51,程序行數(shù)達到了3500行,單片機是ADuC841,顯示器件為240128點陣液晶屏,用來顯示參數(shù)和波形曲線.
在反復的應用研究中,我琢磨出了一套變通的c語言,當然在c的支持范圍之內(nèi).這套變通的c語言,連乘除法運算都用自己的專用子程序,它更加貼近匯編,雖然程序行數(shù)增加了,甚至是明顯增加,但是編譯后的代碼量卻大大減小,速度也很高,在必要的時候插入?yún)R編混合編程,查看代碼,和匯編的效果基本一樣.
少舉幾例:
-----------------------------------------
部分宏:
#define I2(v) HIGH_BYTE_OF_INT(v)
#define I1(v) LOW_BYTE_OF_INT(v)
#define L4(v) HH_BYTE_OF_LONG(v)
#define L3(v) HL_BYTE_OF_LONG(v)
#define L2(v) LH_BYTE_OF_LONG(v)
#define L1(v) LL_BYTE_OF_LONG(v)
#define L43(v) HIGH_INT_OF_LONG(v)
#define L21(v) LOW_INT_OF_LONG(v)
#define L32(v) MID_INT_OF_LONG(v)
#define DIV42(u, v) Ndivide(LOW_INT_OF_LONG(u), HIGH_INT_OF_LONG(u), v)
-----------------------------------------
//顯示累計參數(shù)
//s=0,顯示6位,s=1,顯示8位
void DisLong(ulong alng, uchar s)
{
uchar sh = 0;
alng = DIV42(alng, 10000);
L21(alng) = Ndiv21(L21(alng), 100);
if (s)
{
sh = DisDigit(L1(alng) / 10, sh);
sh = DisDigit(L1(alng) % 10, sh);
}
sh = DisDigit(L2(alng) / 10, sh);
sh = DisDigit(L2(alng) % 10, sh);
L21(alng) = Ndiv21(L43(alng), 100);
sh = DisDigit(L1(alng) / 10, sh);
DisDigit(L1(alng) % 10, sh);
PutEngChar(L2(alng) / 10);
if (dDecNums == 1)
PutEngChar(CODE_POINT);
PutEngChar(L2(alng) % 10);
}
上面這段分位程序,執(zhí)行速度比用/100000,/10000…,/10的方式快五倍以上
------------------------------------------------
//參數(shù)加
void ParaUp1()
{
if (!FlagParaWord) //單字節(jié)
{
if (i2Pointer == &iStartPhase) //參考相位循環(huán)加減
(*(uchar *)(i2Pointer))++;
else if (*(uchar *)(i2Pointer) < LOW_BYTE_OF_INT(i2ParaLimH))
if (i2Pointer == &iPumpDiaA || i2Pointer == &iPumpDiaB)
HIGH_BYTE_OF_INT(*i2Pointer) += 10;
else
HIGH_BYTE_OF_INT(*i2Pointer)++;
} //這個大括號不能少略,以示下面else的對應關系
else //雙字節(jié)
if (*i2Pointer < i2ParaLimH)
(*i2Pointer)++;
FlagParaChanged = 1;
DisSetPara(); //參數(shù)更改后立即顯示更新
}
------------------------------------------------
討論匯編與c的問題,確實不可能得出一個絕對的結(jié)論,這一點我在工作中也感覺到了.不可否認,C程序,按照大路性的編寫方式,其效率確實是個問題,但是對于超大的程序,匯編也是難以支持的.
我最近的一個項目,用的c51,程序行數(shù)達到了3500行,單片機是ADuC841,顯示器件為240128點陣液晶屏,用來顯示參數(shù)和波形曲線.
在反復的應用研究中,我琢磨出了一套變通的c語言,當然在c的支持范圍之內(nèi).這套變通的c語言,連乘除法運算都用自己的專用子程序,它更加貼近匯編,雖然程序行數(shù)增加了,甚至是明顯增加,但是編譯后的代碼量卻大大減小,速度也很高,在必要的時候插入?yún)R編混合編程,查看代碼,和匯編的效果基本一樣.
少舉幾例:
-----------------------------------------
部分宏:
#define I2(v) HIGH_BYTE_OF_INT(v)
#define I1(v) LOW_BYTE_OF_INT(v)
#define L4(v) HH_BYTE_OF_LONG(v)
#define L3(v) HL_BYTE_OF_LONG(v)
#define L2(v) LH_BYTE_OF_LONG(v)
#define L1(v) LL_BYTE_OF_LONG(v)
#define L43(v) HIGH_INT_OF_LONG(v)
#define L21(v) LOW_INT_OF_LONG(v)
#define L32(v) MID_INT_OF_LONG(v)
#define DIV42(u, v) Ndivide(LOW_INT_OF_LONG(u), HIGH_INT_OF_LONG(u), v)
-----------------------------------------
//顯示累計參數(shù)
//s=0,顯示6位,s=1,顯示8位
void DisLong(ulong alng, uchar s)
{
uchar sh = 0;
alng = DIV42(alng, 10000);
L21(alng) = Ndiv21(L21(alng), 100);
if (s)
{
sh = DisDigit(L1(alng) / 10, sh);
sh = DisDigit(L1(alng) % 10, sh);
}
sh = DisDigit(L2(alng) / 10, sh);
sh = DisDigit(L2(alng) % 10, sh);
L21(alng) = Ndiv21(L43(alng), 100);
sh = DisDigit(L1(alng) / 10, sh);
DisDigit(L1(alng) % 10, sh);
PutEngChar(L2(alng) / 10);
if (dDecNums == 1)
PutEngChar(CODE_POINT);
PutEngChar(L2(alng) % 10);
}
上面這段分位程序,執(zhí)行速度比用/100000,/10000…,/10的方式快五倍以上
------------------------------------------------
//參數(shù)加
void ParaUp1()
{
if (!FlagParaWord) //單字節(jié)
{
if (i2Pointer == &iStartPhase) //參考相位循環(huán)加減
(*(uchar *)(i2Pointer))++;
else if (*(uchar *)(i2Pointer) < LOW_BYTE_OF_INT(i2ParaLimH))
if (i2Pointer == &iPumpDiaA || i2Pointer == &iPumpDiaB)
HIGH_BYTE_OF_INT(*i2Pointer) += 10;
else
HIGH_BYTE_OF_INT(*i2Pointer)++;
} //這個大括號不能少略,以示下面else的對應關系
else //雙字節(jié)
if (*i2Pointer < i2ParaLimH)
(*i2Pointer)++;
FlagParaChanged = 1;
DisSetPara(); //參數(shù)更改后立即顯示更新
}
------------------------------------------------
0
回復
@sdjufeng
謝謝,關于你說的問題,我基本是贊同的.討論匯編與c的問題,確實不可能得出一個絕對的結(jié)論,這一點我在工作中也感覺到了.不可否認,C程序,按照大路性的編寫方式,其效率確實是個問題,但是對于超大的程序,匯編也是難以支持的.我最近的一個項目,用的c51,程序行數(shù)達到了3500行,單片機是ADuC841,顯示器件為240128點陣液晶屏,用來顯示參數(shù)和波形曲線.在反復的應用研究中,我琢磨出了一套變通的c語言,當然在c的支持范圍之內(nèi).這套變通的c語言,連乘除法運算都用自己的專用子程序,它更加貼近匯編,雖然程序行數(shù)增加了,甚至是明顯增加,但是編譯后的代碼量卻大大減小,速度也很高,在必要的時候插入?yún)R編混合編程,查看代碼,和匯編的效果基本一樣.少舉幾例:-----------------------------------------部分宏:#defineI2(v)HIGH_BYTE_OF_INT(v)#defineI1(v)LOW_BYTE_OF_INT(v)#defineL4(v)HH_BYTE_OF_LONG(v)#defineL3(v)HL_BYTE_OF_LONG(v)#defineL2(v)LH_BYTE_OF_LONG(v)#defineL1(v)LL_BYTE_OF_LONG(v)#defineL43(v)HIGH_INT_OF_LONG(v)#defineL21(v)LOW_INT_OF_LONG(v)#defineL32(v)MID_INT_OF_LONG(v)#defineDIV42(u,v)Ndivide(LOW_INT_OF_LONG(u),HIGH_INT_OF_LONG(u),v)-----------------------------------------//顯示累計參數(shù)//s=0,顯示6位,s=1,顯示8位voidDisLong(ulongalng,uchars){ ucharsh=0; alng=DIV42(alng,10000); L21(alng)=Ndiv21(L21(alng),100); if(s) { sh=DisDigit(L1(alng)/10,sh); sh=DisDigit(L1(alng)%10,sh); } sh=DisDigit(L2(alng)/10,sh); sh=DisDigit(L2(alng)%10,sh); L21(alng)=Ndiv21(L43(alng),100); sh=DisDigit(L1(alng)/10,sh); DisDigit(L1(alng)%10,sh); PutEngChar(L2(alng)/10); if(dDecNums==1) PutEngChar(CODE_POINT); PutEngChar(L2(alng)%10);}上面這段分位程序,執(zhí)行速度比用/100000,/10000…,/10的方式快五倍以上------------------------------------------------//參數(shù)加voidParaUp1(){ if(!FlagParaWord) //單字節(jié) { if(i2Pointer==&iStartPhase) //參考相位循環(huán)加減 (*(uchar*)(i2Pointer))++; elseif(*(uchar*)(i2Pointer)
支持
0
回復