今天,我們來聊聊函數(shù)是怎么傳入參數(shù)的,我們都知道,當一個函數(shù)調(diào)用使用少量參數(shù)(ARM上是少于等于4個)時,參數(shù)是通過寄存器進行傳值(ARM上是通過r0,r1,r2,r3),而當參數(shù)多于4個時,會將多出的參數(shù)壓入棧中進行傳遞(其實在函數(shù)調(diào)用過程中也會把r0,r1,r2,r3傳遞的參數(shù)壓入棧),具體是什么實現(xiàn)的呢,下面我們來具體看看。
函數(shù)棧
首先我們需要了解一下linux下一個進程的內(nèi)存地址空間是如何布局的,在linux中,0~3G的虛擬地址為進程所有,3G~4G由內(nèi)核所使用,每一個進程都有自己獨立的0~3G內(nèi)存地址空間。當進程進行函數(shù)調(diào)用時,我們都知道傳入被調(diào)用函數(shù)的參數(shù)是通過棧進行操作的,這里我們只需要簡單了解一下linux的內(nèi)存地址空間中的棧是自頂向下生長的,就是棧底出于高地址處,棧頂出于低地址處。
好的,簡單了解了內(nèi)存地址空間的棧后,我們還需要簡單了解一下EBP和ESP這兩個寄存器,EBP是用保存棧低地址的,而ESP用于保存棧頂?shù)刂罚恳淮魏瘮?shù)調(diào)用會涉及到一個棧幀,棧幀結構如下圖
舉個實例詳細說明一下一個函數(shù)幀的特點,比如
/* B被A調(diào)用
* 參數(shù):data1, data2, data3
* 局部變量: s1, s2, s3 */
void B (int data1, int data2, int data3)
{
int b_s1;
int b_s2;
int b_s3;
}
/* A調(diào)用B函數(shù) */
void A (void)
{
int a_s1;
int a_s2;
int a_s3;
B (1, 2, 3);
printf ("1\n");
}
在以上例子中棧幀情況應該如下圖所示
從圖例中可以看出,當A函數(shù)沒有調(diào)用B函數(shù)時,A函數(shù)的棧幀只保存著局部變量,而EBP(棧底指針)指向的是A函數(shù)的函數(shù)棧幀頭,而當A函數(shù)調(diào)用B函數(shù)時,A函數(shù)會將B函數(shù)所需要的參數(shù)從右往左壓入棧(在例子中先壓入3,之后是2,最后是1),之后會將A調(diào)用完B之后所需要運行的第一條指令壓入棧,此時建立一個B的棧幀,具體流程:
從右往左將B函數(shù)所需參數(shù)壓入棧
壓入執(zhí)行完B函數(shù)之后的第一條指令地址
建立B棧幀
壓入A棧幀的棧底
壓入B函數(shù)保護的寄存器
壓入B函數(shù)的局部變量
小結
其實每一種處理器架構所使用的方式都不一樣,在arm上我?guī)讉€參數(shù)和不定參數(shù)的情況通過匯編代碼查看又不相同,今天講的就當做一個入門知識吧。
-
寄存器
+關注
關注
31文章
5359瀏覽量
120818 -
Linux
+關注
關注
87文章
11329瀏覽量
209975 -
函數(shù)
+關注
關注
3文章
4344瀏覽量
62813
原文標題:你知道ARM下函數(shù)是怎么傳入?yún)?shù)的嗎?
文章出處:【微信號:gh_c472c2199c88,微信公眾號:嵌入式微處理器】歡迎添加關注!文章轉載請注明出處。
發(fā)布評論請先 登錄
相關推薦
評論