PC(program counter)是CPU中用於存放下一條指令地址的寄存器,SP為堆棧指針。下面將介紹函數調用過程中CPU對PC和SP這兩個寄存器的操作。
假設有如下函數Fun
Fun() { ………………… Sub-fun(a, b); ………………… }
當函數Fun調用其子函數sub-fun時,CPU內部執行情況如下:
1. 執行CPU指令push,將參數a、b入棧,即根據CPU SP寄存器的值,把a、b的值存入SP指向的地址,並把SP減1(棧通常從高地址向低地址生長)。
2. 執行CPU指令call,CPU會把目前PC寄存器的值push到heap中,這個動作意味着存儲返回地址。
3. 接着CPU把PC寄存器的值設為函數sub-fun的地址,則下個被執行的指令就是函數sub-fun的第一行語句。
4. 當函數sub-fun在執行時,可以根據目前SP寄存器的值計算出參數a、b的地址。
5. 如果函數sub-fun有定義局部變量,這些變量的地址會從目前heap的頂端繼續生長(這就是為什么我們在嵌入式開發時,總是會要求應用程序工程不要定義size太大的局部變量,否則容易導致棧溢出的原因)。
6. 當函數sub-fun執行完畢后,CPU會執行ret指令,這個命令會從heap頂端pop出返回地址——即調用sub-fun之前Fun函數執行到的語句的地址,然后更改PC寄存器的值為這個返回地址,則下個指令就會返回執行函數sub-fun的下一行語句,從而完成了函數調用。