2015-06-30 62 views
3

我在裝配中的知識有限,但我至少可以通讀它並與相應的C或C++代碼匹配。我可以看到函數參數是通過將它們推入堆棧或通過寄存器傳遞的,函數體使用一些寄存器來執行操作。但它似乎也使用了調用者使用的相同寄存器。這是否意味着調用者不能保證函數調用後寄存器的狀態是相同的?如果在編譯期間函數的整個主體是未知的,該怎麼辦?編譯器如何處理這個問題?函數調用後寄存器的狀態是什麼?

+5

它取決於函數的[調用約定](https://en.wikipedia.org/wiki/Calling_convention)。對於x86 cdecl,EAX是返回值,ECX和EDX必須由調用者保存;其餘的必須由被調用者保存。 –

+1

不僅是調用約定,還有特定編譯器關於優化的策略以及它自己的特性。 – Robinson

+0

答案主要取決於編譯器和操作系統。 –

回答

3

編譯器生成的彙編代碼遵循calling convention。調用約定通常指定

  • 如何傳遞給函數的參數
  • 返回值是如何從被調用函數傳遞給調用者
  • 哪些寄存器要保存一個函數調用內可以進行修改

如果被調用的所有函數遵循相同的調用約定,則不會發生使用相同寄存器的問題。

2

正如評論所暗示的那樣,事實是沒有這方面的標準。它完全留給你正在使用的特定C++編譯器的實現者。

一個更明確的問題,如下所示:「使用ABI E編譯帶有編譯器選項B的編譯器A的版本N,爲目標CPU D調用C的函數簽名時,有什麼保證,可見寄存器保存?「

在這種情況下,該特定工具集的專家(或手冊)可以回答。你可以推斷,對於任何類型的工業強度項目,這是一個錯誤的問題,因爲隨着編譯器的發展,答案將會改變,而且你不希望這個事實影響你的可靠性程序。

這是一個很好的問題,因爲很高興知道編譯器正在做什麼 - 它有助於學習。但總的來說,黃金法則是在程序中向編譯器表達清晰的簡單邏輯,並允許編譯器處理將該邏輯轉換爲優化機器代碼的細節,在此代碼中現代編譯器非常出色。

+0

它不僅僅是編譯器,而是大多數語言,體系結構/ CPU和操作系統。對於某些體系結構,有多個ABI(例如,ARM,x86 - 在Windows或Linux(OS-X?)上)。 – Olaf

+0

@Olaf的確如此,我的意思是「編譯器」這個術語能夠捕捉到所有這些,但我會在答案中明確指出。 –

+0

好吧,你是讓它太泛泛......如果我在Windows上的x86架構上用C調用約定來聲明函數foo(),那麼......我會一直知道會發生什麼,無論如何編譯器版本(或其選項)。如果不是這樣,你甚至不能調用OS庫函數。 –

相關問題