|
|||||||||||
| 技術(shù)交流 | 電路欣賞 | 工控天地 | 數(shù)字廣電 | 通信技術(shù) | 電源技術(shù) | 測(cè)控之家 | EMC技術(shù) | ARM技術(shù) | EDA技術(shù) | PCB技術(shù) | 嵌入式系統(tǒng) 驅(qū)動(dòng)編程 | 集成電路 | 器件替換 | 模擬技術(shù) | 新手園地 | 單 片 機(jī) | DSP技術(shù) | MCU技術(shù) | IC 設(shè)計(jì) | IC 產(chǎn)業(yè) | CAN-bus/DeviceNe |
Keil C51的一些有趣特性 |
| 作者:yanfengzhu 欄目:單片機(jī) |
首先得說的是我是菜鳥,在此論壇上學(xué)了很多的東東。但是今年以來,論壇上似乎沒有了去年一大幫高手討論問題的場面了,似乎失去了往日的風(fēng)光了。在此我那出我近日一些不成熟的想法,希望大家斧正。有啥不正確的,請(qǐng)一定告之與我。 Keil C51的一些有趣特性 作者:yanfeng E-mail:szq106@163.com Keil c51號(hào)稱作為51系列單片機(jī)最好的開發(fā)環(huán)境,大家一定都很熟悉。它的一些普通的特性大家也都了解,(書上也都說有)如:因?yàn)?1內(nèi)的RAM很小,C51的函數(shù)并不通過堆棧傳遞參數(shù)(重入函數(shù)除外),局部變量也不存儲(chǔ)在堆棧中,而是存在于固定的RAM中及寄存器中。那么看一下下面的程序。 void fun1(unsigned CHAR i) { … } 正常情況參數(shù)i通過R7傳入函數(shù),那么它的實(shí)際地址在什么地方呢?就是R7嗎?回答這個(gè)問題之前我們先來了解keil c51的幾個(gè)有趣的特性(不考慮重入函數(shù))。 一、 函數(shù)在調(diào)用前定義與在調(diào)用后定義產(chǎn)生的代碼是有很大差別的(特別是在優(yōu)化級(jí)別大于3級(jí)時(shí))。(本人也不太清楚為什么,大概因?yàn)樵谡{(diào)用前定義則調(diào)用函數(shù)已經(jīng)知道被調(diào)用函數(shù)對(duì)寄存器的使用情況,則可對(duì)函數(shù)本身進(jìn)行優(yōu)化;而在調(diào)用后進(jìn)行定義則函數(shù)不知被調(diào)用函數(shù)對(duì)寄存器的使用情況,它默認(rèn)被調(diào)用函數(shù)對(duì)寄存器(ACC、 B、 DPH、 DPL、 PSW、 R0、 R1、 R2、 R3、R 4、 R5、, R6、 R7)都已經(jīng)改變,因此不在這些寄存器中存入有效的數(shù)據(jù)) 二、 函數(shù)調(diào)用函數(shù)時(shí)除在堆棧中存入返回地址之外,不在堆棧中保存其它任何寄存器(ACC、 B、 DPH、 DPL、 PSW、 R0、 R1、 R2、 R3、R 4、 R5、, R6、 R7)的內(nèi)容。(除非被調(diào)用函數(shù)使用了using特性) 三、 中斷函數(shù)是一個(gè)例外,它會(huì)計(jì)算自身及它所調(diào)用的函數(shù)對(duì)寄存器(ACC、 B、 DPH、 DPL、 PSW、 R0、 R1、 R2、 R3、R 4、 R5、, R6、 R7)的改變,并保存相應(yīng)它認(rèn)為被改變了的寄存器。 四、 使用C寫程序時(shí),盡量少使用using n (n=0,1,2,3)特性。(這個(gè)特性在本人使用的過程中存在一些問題,不知算不算是一個(gè)小bug) 以下的試驗(yàn)都是在(環(huán)境 keil c51 v7.20)中,優(yōu)化級(jí)為default下完成。 先看第一個(gè)特性問題。 例1: void fun2(void) { } void fun1(unsigned CHAR i) { fun2(); while(i--); } 它的匯編代碼如下: ; void fun2(void) RSEG ?PR?fun2?TEST fun2: ; SOURCE LINE # 12 ; { ; SOURCE LINE # 13 ; } ; SOURCE LINE # 14 RET ; END OF fun2 ; ; void fun1(unsigned CHAR i) RSEG ?PR?_fun1?TEST _fun1: USING 0 ; SOURCE LINE # 16 ;---- Variable 'i?240' assigned to Register 'R7' ---- ; { ; SOURCE LINE # 17 ; fun2(); ; SOURCE LINE # 18 LCALL fun2 ?C0003: ; while(i--); ; SOURCE LINE # 19 MOV R6,AR7 DEC R7 MOV A,R6 JNZ ?C0003 ; } ; SOURCE LINE # 20 ?C0005: RET ; END OF _fun1 從中可以看到fun2()在fun1()前先定義,fun1()知道fun2()對(duì)寄存器的使用情況,知道R7沒有改變,而參數(shù)i存于R7中,即i既是R7。(;---- Variable 'i?140' assigned to Register 'R7' ----) 看另一情況 void fun2(void); void fun1(unsigned CHAR i) { fun2(); while(i--); } void fun2(void) { } 匯編代碼如下: ; void fun1(unsigned CHAR i) RSEG ?PR?_fun1?TEST _fun1: USING 0 ; SOURCE LINE # 14 MOV i?140,R7 ; { ; SOURCE LINE # 15 ; fun2(); ; SOURCE LINE # 16 LCALL fun2 ?C0002: ; while(i--); ; SOURCE LINE # 17 MOV R7,i?140 DEC i?140 MOV A,R7 JNZ ?C0002 ; } ; SOURCE LINE # 18 ?C0004: RET ; END OF _fun1 ; ; void fun2(void) RSEG ?PR?fun2?TEST fun2: ; SOURCE LINE # 20 ; { ; SOURCE LINE # 21 ; } &nbs |
| 2樓: | >>參與討論 |
| 作者: enbed 于 2005/6/1 14:28:00 發(fā)布:
這個(gè): 由此可以推論出,一個(gè)高優(yōu)先級(jí)的中斷函數(shù)及一個(gè)低優(yōu)先級(jí)的中斷函數(shù)同時(shí)使用了using n,(n = 0,1,2,3)當(dāng)n相同時(shí),這個(gè)存在的bug 是多么的隱蔽。(這恰是使人想象不到的) 你沒有用過匯編把. 一般匯編都這么用,會(huì)自己事先把四個(gè)寄存器組分配好的. |
|
| 3樓: | >>參與討論 |
| 作者: meng730507 于 2005/6/1 14:56:00 發(fā)布:
有點(diǎn)意思! |
|
| 4樓: | >>參與討論 |
| 作者: 來與君 于 2005/6/1 15:24:00 發(fā)布:
在不同的中斷服務(wù)例程中使用寄存器組切換時(shí) 在using上是要仔細(xì)處理的 沒有什么理由在用匯編寫時(shí)就很細(xì)心,而用C寫時(shí)就可以馬虎這種道理的。 畢竟開發(fā)環(huán)境這個(gè)工具不是完美的。 |
|
| 5樓: | >>參與討論 |
| 作者: yanfengzhu 于 2005/6/1 15:25:00 發(fā)布:
謝謝兩位捧場。 |
|
| 6樓: | >>參與討論 |
| 作者: yanfengzhu 于 2005/6/1 15:43:00 發(fā)布:
to enbed 我是從匯編學(xué)起的,要說不懂也懂那么一點(diǎn)。(也許不比論壇上的大部分人差哦。 用匯編來寫我肯定不會(huì)出這個(gè)錯(cuò)誤!但是C語言是編譯器編譯的。這個(gè)就不大好說了。比如定時(shí)器0和定時(shí)器1中斷函數(shù)同時(shí)使用了using 1,而定時(shí)器0設(shè)為低優(yōu)先級(jí),定時(shí)器1設(shè)為高優(yōu)先級(jí)。在某種情況下,定時(shí)器0進(jìn)入中斷后,定時(shí)器1也進(jìn)入中斷。這樣形成兩級(jí)中斷嵌套。由于中斷函數(shù)使用了using 1不再保存R0 -- R7的值,當(dāng)定時(shí)器0中斷函數(shù)在R0--R7中存放有重要數(shù)據(jù)而定時(shí)器1中斷函數(shù)破壞了R0--R7的值時(shí),程序會(huì)出現(xiàn)什么情況就很難說了。因?yàn)橹袛嗲短壮霈F(xiàn)的情況本身不是常見,而高低級(jí)中斷函數(shù)都使用R0--R7情況也不多,因此才說這個(gè)bug很隱蔽。 |
|
| 7樓: | >>參與討論 |
| 作者: yanfengzhu 于 2005/6/1 15:50:00 發(fā)布:
to 來與君 謝謝! 不是說寫程序馬虎,只是發(fā)現(xiàn)了提出來提示大家,免得犯同樣的錯(cuò)誤。 |
|
| 8樓: | >>參與討論 |
| 作者: enbed 于 2005/6/1 16:12:00 發(fā)布:
來與君的是正解. 這個(gè)問題是你不同的中斷錯(cuò)誤的使用同一個(gè)寄存器組,怎么能說是編譯器的錯(cuò)誤? |
|
| 9樓: | >>參與討論 |
| 作者: 狂日 于 2005/6/1 16:18:00 發(fā)布:
GLOBAL Register Coloring 對(duì)于“函數(shù)在調(diào)用前定義與在調(diào)用后定義產(chǎn)生的代碼是有很大差別的” 請(qǐng)打開GLOBAL Register Coloring開關(guān)試試! |
|
| 10樓: | >>參與討論 |
| 作者: zalin 于 2005/6/1 17:39:00 發(fā)布:
沒仔細(xì)看使用手冊(cè) KEIL C51的使用手冊(cè)對(duì)中斷函數(shù)使用“USING”和在中斷函數(shù)中調(diào)用函數(shù)有明確的說明 不同優(yōu)先級(jí)的中斷函數(shù)不要使用相同的寄存器BANK,假如使用了“USING” 在中斷函數(shù)中被調(diào)用的函數(shù)應(yīng)和中斷函數(shù)使用相同的寄存器BANK,除非對(duì)被調(diào)用的函數(shù)使用“NOAREGS” |
|
| 11樓: | >>參與討論 |
| 作者: cxd731 于 2005/6/1 17:56:00 發(fā)布:
C51的書沒啃透! |
|
| 12樓: | >>參與討論 |
| 作者: yanfengzhu 于 2005/6/2 9:14:00 發(fā)布:
謝大家 to enbed 51本身沒有限定不同的中斷不能使用同一個(gè)寄存器組。Keil c51不能這么使用本身不能不是說存在小瑕疵,而且我并沒說這是編譯器的大錯(cuò)誤。甚至于算不算一個(gè)小bug也還有待商榷。 to 狂日 GLOBAL Register Coloring是優(yōu)化級(jí)別還是? to zalin 老實(shí)說,KEIL C51的使用手冊(cè)的確實(shí)沒仔細(xì)看,謝謝提醒。 謝謝各位。 |
|
| 13樓: | >>參與討論 |
| 作者: foolembed 于 2005/6/2 9:34:00 發(fā)布:
你是翻譯的,還是自己寫的啊,呵呵:) keil的手冊(cè)可是差不多都有了把, 會(huì)總結(jié)的人,進(jìn)步最快,欣賞:) 由此可以推論出,一個(gè)高優(yōu)先級(jí)的中斷函數(shù)及一個(gè)低優(yōu)先級(jí)的中斷函數(shù)同時(shí)使用了using n,(n = 0,1,2,3)當(dāng)n相同時(shí),這個(gè)存在的bug 是多么的隱蔽。(這恰是使人想象不到的) 正如enbed所說,用過asm的人,應(yīng)該知道寄存器保護(hù)的,而且keil也很明確的告訴了大家:千萬不要這樣使用using在中斷編程的時(shí)候:), keil的資料大把,高手n多, 但感謝你將這樣的資料翻譯或者是整理出來,很多初學(xué)者還是會(huì)很受用的:) 贊! |
|
| 14樓: | >>參與討論 |
| 作者: yanfengzhu 于 2005/6/2 9:51:00 發(fā)布:
to foolembed 是我自己寫的,因?yàn)榻鼇碓谡夜ぷ鳎]人要。苁聼o聊,于是想學(xué)習(xí)一下OS,在寫os的過程中發(fā)現(xiàn)這些有趣的東東的。我的小OS就寫好了,最大的特點(diǎn)的全C寫成,沒有一句匯編。有時(shí)間整理上來,到時(shí)望各位高手指教. |
|
| 15樓: | >>參與討論 |
| 作者: nizq 于 2005/6/2 18:44:00 發(fā)布:
GOOD。! |
|
| 16樓: | >>參與討論 |
| 作者: hunter01 于 2005/6/2 20:07:00 發(fā)布:
并不是什么bug,中斷優(yōu)先級(jí)不同,不一定就嵌套. 中斷優(yōu)先級(jí)不同,不一定就嵌套,進(jìn)入地優(yōu)先級(jí)中斷,可可以屏蔽一下高優(yōu)先級(jí)中斷, 編譯器編譯的結(jié)果是正確的。 而且兩個(gè)中斷不可能同時(shí)出現(xiàn)的 情況也是經(jīng)常用到的的,比如在產(chǎn)口中斷里啟動(dòng)和停止定時(shí)器 * - 本貼最后修改時(shí)間:2005-6-2 20:15:41 修改者:hunter01 |
|
| 17樓: | >>參與討論 |
| 作者: 來與君 于 2005/6/2 20:19:00 發(fā)布:
再進(jìn)來是為了稱贊樓主的 嘗試著去剖析一個(gè)工具是為了更好地利用它,我偶爾也這么做。 你提到的“51本身沒有限定不同的中斷不能使用同一個(gè)寄存器組。Keil c51不能這么使用本身不能不是說存在小瑕疵,而且我并沒說這是編譯器的大錯(cuò)誤。甚至于算不算一個(gè)小bug也還有待商榷! 就另外一件事情來看,我是這么理解Keil的。 以帶Carry位的移位操作來說,在某些應(yīng)用中,用ASM來實(shí)現(xiàn)非常有用且高效,但在Keil C中未有直接對(duì)應(yīng)的操作指令。這是Keil對(duì)CY位不了解嗎?不會(huì)用嗎?在這上面它考慮的也許更多的是一個(gè)C程序的移植。 因此,不要因?yàn)槟承┓矫鍯沒有如ASM一般動(dòng)作而直接否定Keil C的機(jī)理。我想,Keil在51場子里頭摸爬滾打這么些年,它對(duì)51的特性比我們稍熟一些。 當(dāng)然,Keil C也有Bug,這從它的發(fā)行筆記中就可以看到。不過,這些Bug往往不在51的特性上。 |
|
| 18樓: | >>參與討論 |
| 作者: st963432 于 2005/6/3 8:38:00 發(fā)布:
好 |
|
| 19樓: | >>參與討論 |
| 作者: gxlww 于 2005/6/3 20:26:00 發(fā)布:
高! |
|
| 20樓: | >>參與討論 |
| 作者: go_by_wind 于 2005/6/3 21:42:00 發(fā)布:
好帖子呀,頂一下。。 |
|
| 21樓: | >>參與討論 |
| 作者: rogerllg 于 2005/6/4 10:39:00 發(fā)布:
不錯(cuò) 還是頂一下。。。。。 |
|
| 22樓: | >>參與討論 |
| 作者: zj_hfp 于 2005/6/4 13:58:00 發(fā)布:
很好 我在實(shí)際調(diào)試中,遇到一個(gè)怪事,要在代碼中加入 ACC=0XFF;,原因可能是hfpfx的數(shù)變了,是取ACC的數(shù)了。真怪。 for(i=0;i<6;i++) //提升位置處理 { ACC=0XFF; //系統(tǒng)內(nèi)部原因一定要加 tmp=hfpfx<<i; tmp=tmp&0x80; tmp1=hfpfx1<<i; tmp1=tmp1&0x80; ACC=0; if (tmp!=tmp1) send[i]=0; } |
|
| 23樓: | >>參與討論 |
| 作者: icxlh 于 2005/6/5 11:57:00 發(fā)布:
向強(qiáng)者學(xué)習(xí) |
|
| 24樓: | >>參與討論 |
| 作者: haotz 于 2005/6/5 13:29:00 發(fā)布:
瞎掰 |
|
| 25樓: | >>參與討論 |
| 作者: yanfengzhu 于 2005/6/5 14:31:00 發(fā)布:
to haotz 此帖正是瞎掰,偶爾有閑情瞎掰一下也是好事嘛。 |
|
| 26樓: | >>參與討論 |
| 作者: 莊莊 于 2005/6/5 17:35:00 發(fā)布:
請(qǐng)問怎樣能把反匯編的程序復(fù)制出來,謝謝 你這里既有C語言源程序又有匯編程序,請(qǐng)問怎樣能把反匯編的程序復(fù)制出來,謝謝 |
|
| 27樓: | >>參與討論 |
| 作者: xuefeihu 于 2005/6/5 20:02:00 發(fā)布:
ding yixia |
|
| 28樓: | >>參與討論 |
| 作者: ypli 于 2005/6/6 18:19:00 發(fā)布:
挺不錯(cuò)的!善于發(fā)現(xiàn)和思考!我喜歡! |
|
| 29樓: | >>參與討論 |
| 作者: leejun101 于 2005/6/7 10:36:00 發(fā)布:
高手啊,俺是初學(xué)者 |
|
| 30樓: | >>參與討論 |
| 作者: 235 于 2005/6/11 23:19:00 發(fā)布:
太帥了。 真的,以前寫程序,只要能執(zhí)行的通就行,從不會(huì)關(guān)心代碼優(yōu)化的問題。這次算開眼界了。 呵呵,頂。 |
|
|
|
| 免費(fèi)注冊(cè)為維庫電子開發(fā)網(wǎng)會(huì)員,參與電子工程師社區(qū)討論,點(diǎn)此進(jìn)入 |
Copyright © 1998-2006 m.58mhw.cn 浙ICP證030469號(hào) |