函數呼叫 (Function Call)        參考1  參考2      

以硬體的觀念來講,函數是放在記憶體中的一群指令,而每個函數被放置在不同的記憶體,如下圖所示:
 ┌──────────────────────────┐
 │  ┌───────────────────────┐  │
 │  │IP↘                                                                 code (text)   │  │
 │  │     ┌───┐      ┌────┐    ┌────┐      │  │
 │  │     │main(  )│      │函數 A( )│    │函數 B(  )│      │  │
 │  │     └───┘      └────┘    └────┘         │  │
 │  └───────────────────────┘  │
 │        ┌──────┐┌───┐┌────────┐    │
 │        │   data heap   ││ stack    ││ global name space  │    │
 │        └──────┘└───┘└────────┘    │
 └──────────────────────────┘
   code:放置程式碼的區塊,也叫做 text,意即程式的本文之意。
   data heap:所有的區域變數都被放在這裡。
   stack:此塊記憶體是給編譯程式和作業系統應用的,我們通常無法直接取用。
   global name space:放置所有的靜態變數、全域變數以及外部變數。(在 UNIX 系統下這塊記憶體也叫做 bss)

一個程式佔據多大的記憶體,在 UNIX 系統下可以用 size 這個指令看出來,例如我們想看看 gcc 佔了多大的記憶體空間:
  [thccy14]/usr/local/bin> size gcc
  text    data    bss     dec     hex     filename
  57312   8192    0       65504   ffe0    gcc
 可以看到 gcc 的 code 有 57312 bytes,需要 8192 bytes 的 data heap,不需要 bss。

程式的執行過程:
首先,有一個叫做IP(Instruction Pointer,CPU 會依序執行IP所指位址的指令)的暫存器會指向程式開始的地方
(通常是 main 函數),當函數呼叫發生時,硬體按照下列的流程執行程式的控制權轉移:

                           函數呼叫發生
                                ↓
                 把目前的程式執行狀態存進 stack (含 IP) ,把函數的參數由右而左存進 stack
                                            ↓
                     把 IP 指向欲前往的函數
                                ↓
                            前往函數

進入函數之後,函數由 stack 取得參數 (這部份的碼由編譯器自動產生)之後,開始執行,執行完畢時依以下的流程交回控制權:

                              函數結束
                                 ↓
                        將傳回值存入 stack
                                 ↓
                   取出 stack 中原程式執行狀態,恢復原程式執行狀態
                                          ↓
                        取出傳回值,儲存目前的IP
                                          ↓
                      繼續執行原來的程式

每呼叫一次函數, CPU 就必須浪費很多時間來處理這些記憶體的儲存和更新,會使執行的速度變慢,
所以說遞迴函數不斷地執行函數的呼叫,因此會使執行速度較慢。


一個 activation record (stack frame) 儲存程式的:
–參數與本地變數
–執行結果(回傳值)
–返回位址(return address)
–其他環境資訊(詳見第6單元)
當一個程式被呼叫執行時,系統會自動配置一個activation record (stack frame)給它儲存以上資訊,
並且push這些資訊到stack;副程式執行結束時,便從其activation record中取得返回位址,回到上一層
(當初呼叫它的)程式繼續執行下一句,而系統也在此時收回它的 A.V。
同一支執行中程式的所有副程式的 A.V,都是放在同一個 stack 上,先進後出。
有些書把這個 stack 叫做 system stack (系統堆疊)。

arrow
arrow
    全站熱搜

    Y CP 發表在 痞客邦 留言(0) 人氣()