天天看點

嵌入式程式調用函數的内部過程和機制

在嵌入式程式中,當一個函數調用發生時,它的内部機理是什麼,執行了哪些步驟?如下所示是一個程式在運作時,它的記憶體分布狀況。

嵌入式程式調用函數的内部過程和機制

當一個程式開始運作時,它的代碼被裝入到記憶體,儲存在代碼區,包括主函數和其他函數的代碼。另外,還有三塊記憶體區域用來存放資料。第一塊是全局變量區域,存放了程式當中的所有全局變量。由于全局變量的個數和大小是已知的,是以這一塊區域所占用的記憶體大小在開始時即可确定下來,它們被稱為是靜态配置設定。位于此區域内的變量,它們在程式的整個運作過程當中,都一直存在,隻有當整個程式運作結束了, 這一塊記憶體區域才會被釋放。第二塊區域是棧(stack)區域,它包含了所有的棧幀。所謂的棧幀( stack frame),就是在調用一個函數時,系統會自動地配置設定一塊記憶體區域給這個函數,用來儲存它的運作上下文、形參和局部變量等資訊,這樣的一塊記憶體區域,就叫做一個棧幀。棧幀是在函數調用時配置設定的,當函數調用結束之後,相應的棧幀就會被釋放。是以,對于一個函數的局部變量來說,隻有當函數調用發生時,系統才會給這個函數的形參和局部變量配置設定存儲空間;當函數調用結束後,這些局部變量就被釋放掉了。另外,由于棧區域是由系統自動來配置設定的,使用者并不需要去關心,是以也稱為是自動配置設定。第三塊區域是堆(heap) 區域,它主要是用作動态配置設定的記憶體。

嵌入式程式調用函數的内部過程和機制

如上圖所示是函數調用的一個例子,它考察的是最簡單的一種情形,即在整個程式當中,隻有一個main函數。在這種情況下,當程式開始運作時,它就會被裝入到記憶體。它的代碼存放在記憶體的代碼區域。由于在這個程式中定義了一個全局變量z,是以就在記憶體的全局變量區域配置設定了一個存儲單元給它,并且把它初始化為0。接下來,系統就要調用主函數main去運作了,當這個函數調用發生時,系統就會在棧中給它配置設定一塊記憶體空間,即一個棧幀,用來存放主函數當中所定義的局部變量,即x和y。随後,程式計數器PC就跳轉到主函數的第一條語句, 開始執行。當main函數執行完後,首先要把它所占用的棧幀釋放掉。對于任何一次函數調用來說,在函數調用結束後,都要把相應的棧幀釋放掉,是以x和y這兩個局部變量所占用的存儲空間就被釋放掉了,不能再通路了。接下來,由于main函數是一個特殊的函數,當它執行完之後,整個程式也就結束了。

當一次函數調用發生時,它的執行過程可以歸納為以下5個步驟:

在記憶體的棧空間當中為其配置設定一個棧幀,用來存放該函數的形參變量和局部變量。

把實參變量的值複制到相應的形參變量中。

控制流轉移到該函數的起始位置。

該函數開始執行。

當這個函數執行完以後,控制流和傳回值傳回到函數調用點。

如下圖所示是變量的存儲與作用域的一個例子。

嵌入式程式調用函數的内部過程和機制