函數調用返回值傳遞的三種情形

這篇文章是從《程序員的自我修養》中摘錄的一小點。我個人認爲很不錯,就總結了一下。一般情況下,我們都知道返回值是通過eax這個寄存器返回的。但是,eax本身只能存儲4個字節的數據,對於那些返回值大於4個字節的數據應該怎麼返回呢?下面我們把它分爲3中情況:
第一種情形:小於四個字節。解決之道:直接放到eax中返回。
第二種情形:大於四個字節,小於8個字節。解決之道:採用eax和edx聯合方式進行。eax存儲返回值的低4個字節,edx存儲返回值的高四個字節。
第三種情形:大於8個字節。這就是本篇要研究的內容。


以下面的代碼爲例,

從上述代碼可知,return_test()返回的一個128字節的數據結構,怎麼辦呢?


接下來,我們將從頭到尾理一下思路:
1,首先我們在main函數的棧幀上開闢一片空間,我們這裏假設開始時main棧幀的地址爲Old_ebp,變量n存放在Old_ebp - 88h的地址處。而【Old_ebp-1D0h,Old_ebp - 88h】這段空間地址作爲臨時空間temp,接收從被調用函數返回的數據。
2,將temp對象的地址,也就是Old_ebp-1D0h作爲隱藏參數傳遞給return_test()函數。
3,在return_test()函數的棧幀上,我們爲局部變量b創建了128字節的空間,並對它進行了賦值。然後將這些數據拷貝給temp對象。怎麼拷貝的呢?因爲我們的temp對象的地址爲Old_ebp-1D0h,它是作爲隱含參數傳遞進來的,因此,通過edp+8直接就可以找到temp對象的地址了。然後,將temp對象的地址用eax傳出。爲什麼要返回temp對象這個地址呢?因爲return_test()返回後,它的棧幀也同樣撤銷了,所以到main函數後,我們需要temp對象的地址來把它裏面的內容拷貝到變量n處(Old_ebp - 88h)。
4,return_test()返回後,main函數將eax指向的temp對象中的內容拷貝給n,OK!


整個流程如圖所示。


同樣可以用僞代碼表示

發佈了259 篇原創文章 · 獲贊 7 · 訪問量 51萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章