Keil C51 Data Overlaying
一般的編譯器將函數(shù)中的區(qū)域變數(shù)動(dòng)態(tài)配置在stack,等函數(shù)結(jié)束空間就釋放出來。因?yàn)?051 的內(nèi)部記憶體很少,只有區(qū)區(qū)128 或256 bytes,而且stack 也是共用這塊記憶體。為了節(jié)省stack 空間,所以區(qū)域變數(shù)基本上是靜態(tài)配置在固定位址,也就是變成全域變數(shù)。如此就又造成浪費(fèi)記憶體的情況,為了解決這個(gè)問題,所以8051 的編譯器基本上都采用所謂的data overlaying 技術(shù)來克服區(qū)域變數(shù)浪費(fèi)空間的問題。
所謂data overlaying 是指沒有呼叫關(guān)系的函數(shù),它們的區(qū)域變數(shù)區(qū)可以重疊在一起(共用一塊記憶體)。Keil C51 會(huì)分析程式中函數(shù)間呼叫的關(guān)系,產(chǎn)生一個(gè)呼叫樹。它就根據(jù)這個(gè)呼叫樹來決定那些函數(shù)的區(qū)域變數(shù)區(qū)可以overlaying 在一起。一種情況是是編譯器發(fā)現(xiàn)某一個(gè)函數(shù)(不是main)沒有被別的函數(shù)呼叫,這會(huì)造成編譯器的困惑。一個(gè)正常的程式,除了main 之外,除非是垃圾程式碼(沒用處但沒有刪除),否則所有的函數(shù)應(yīng)該是至少會(huì)被一個(gè)其它函數(shù)呼叫的。編譯器在安全至上的原則下,會(huì)認(rèn)定它的分析無法正確的辨識(shí)這個(gè)函數(shù)呼叫關(guān)系,所以對(duì)這個(gè)函數(shù)的區(qū)域變數(shù)就會(huì)獨(dú)立配置,不會(huì)重疊配置。這樣有沒有問題?邏輯上當(dāng)然不會(huì)有問題,但沒overlaying 就是會(huì)浪費(fèi)記憶體,而且也會(huì)一直產(chǎn)生*** WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS的警告。
什么情況下,函數(shù)的呼叫樹讓編譯器無法分析?真實(shí)應(yīng)用是有一些情況會(huì)發(fā)生這樣的問題。最常見的就是使用函數(shù)指標(biāo)來呼叫函數(shù)。因?yàn)楹艚惺菆?zhí)行時(shí)期動(dòng)態(tài)變動(dòng)的,這就可以難倒編譯器了。在這種情況這些被呼叫的指標(biāo)函數(shù)就會(huì)獨(dú)立配置它們的區(qū)域奱數(shù)。如果你要這些函數(shù)也能正確的使用overlaying 的好處,那么你就必需手動(dòng)分析那些函數(shù)的呼叫樹,然后告訴編譯器就可以了。這樣你也就不會(huì)在編譯時(shí)產(chǎn)UNCALLED SEGMENT 的警告了。