我在裝配中的知識有限,但我至少可以通讀它並與相應的C或C++代碼匹配。我可以看到函數參數是通過將它們推入堆棧或通過寄存器傳遞的,函數體使用一些寄存器來執行操作。但它似乎也使用了調用者使用的相同寄存器。這是否意味着調用者不能保證函數調用後寄存器的狀態是相同的?如果在編譯期間函數的整個主體是未知的,該怎麼辦?編譯器如何處理這個問題?函數調用後寄存器的狀態是什麼?
回答
編譯器生成的彙編代碼遵循calling convention。調用約定通常指定
- 如何傳遞給函數的參數
- 返回值是如何從被調用函數傳遞給調用者
- 哪些寄存器要保存一個函數調用內可以進行修改
如果被調用的所有函數遵循相同的調用約定,則不會發生使用相同寄存器的問題。
正如評論所暗示的那樣,事實是沒有這方面的標準。它完全留給你正在使用的特定C++編譯器的實現者。
一個更明確的問題,如下所示:「使用ABI E編譯帶有編譯器選項B的編譯器A的版本N,爲目標CPU D調用C的函數簽名時,有什麼保證,可見寄存器保存?「
在這種情況下,該特定工具集的專家(或手冊)可以回答。你可以推斷,對於任何類型的工業強度項目,這是一個錯誤的問題,因爲隨着編譯器的發展,答案將會改變,而且你不希望這個事實影響你的可靠性程序。
這是一個很好的問題,因爲很高興知道編譯器正在做什麼 - 它有助於學習。但總的來說,黃金法則是在程序中向編譯器表達清晰的簡單邏輯,並允許編譯器處理將該邏輯轉換爲優化機器代碼的細節,在此代碼中現代編譯器非常出色。
它不僅僅是編譯器,而是大多數語言,體系結構/ CPU和操作系統。對於某些體系結構,有多個ABI(例如,ARM,x86 - 在Windows或Linux(OS-X?)上)。 – Olaf
@Olaf的確如此,我的意思是「編譯器」這個術語能夠捕捉到所有這些,但我會在答案中明確指出。 –
好吧,你是讓它太泛泛......如果我在Windows上的x86架構上用C調用約定來聲明函數foo(),那麼......我會一直知道會發生什麼,無論如何編譯器版本(或其選項)。如果不是這樣,你甚至不能調用OS庫函數。 –
- 1. 啓動後的寄存器狀態
- 2. 什麼是約翰遜計數器中的寄生狀態機
- 3. 什麼函數保存樹的狀態?
- 4. dart調試器的狀態是什麼?
- 5. 什麼是專用寄存器?
- 6. 爲什麼MOVWF不影響狀態寄存器?
- 7. 函數調用後,llvm調用者保存的寄存器未重新載入
- 8. 什麼是被調用者和調用者保存的寄存器?
- 9. PIC寄存器(%ebx)是做什麼的?
- 10. 在<C-r>函數調用後恢復寄存器
- 11. 僞隨機數發生器中的狀態函數是什麼?
- 12. 跳轉後寄存器和變量未保存狀態
- 13. 什麼是ESP和EBP寄存器?
- 14. 調用後的python中的線程鎖狀態是什麼subprocess.popen
- 15. ARM程序狀態寄存器
- 16. Z80狀態標誌寄存器
- 17. EBX寄存器用於內存訪問的模式是什麼?
- 18. 爲什麼地址寄存器後置是(A0)+
- 19. 爲什麼在調用main()時,avr-gcc會不自覺地保存寄存器狀態?
- 20. 80x86狀態位。哪些寄存器是可讀的?
- 21. 調用__device__函數是否會影響CUDA中使用的寄存器數量?
- 22. 在函數調用之前保存XMM寄存器
- 23. 寄存器和臨時寄存器有什麼區別?
- 24. 什麼是通用寄存器的一些特殊用途
- 25. 爲什麼在調用一個函數後,這段代碼會跳入同一個寄存器?
- 26. MIPS中的浮點寄存器是哪些數字寄存器?
- 27. 新的X86_64處理器寄存器的名稱是什麼?
- 28. MIPS中$零寄存器的用途是什麼?
- 29. 通用寄存器的內容是什麼?
- 30. 什麼是在Windows上使用的GS寄存器?
它取決於函數的[調用約定](https://en.wikipedia.org/wiki/Calling_convention)。對於x86 cdecl,EAX是返回值,ECX和EDX必須由調用者保存;其餘的必須由被調用者保存。 –
不僅是調用約定,還有特定編譯器關於優化的策略以及它自己的特性。 – Robinson
答案主要取決於編譯器和操作系統。 –