2010-03-01 63 views
7

我目前正在通過Andrew Appel的Java編譯器實現方式,並且我正在構建低級別中間表示法。爲x86處理器生成彙編

最初,我決定瞄準JVM並忽略所有低級機器的東西,但爲了學習我不瞭解的東西,我已經改變了心意。這改變了我的IR,因爲以JVM爲目標允許我(或多或少)在進行方法調用或構建對象時揮手。

Appel的書沒有詳細介紹任何特定的機器架構,所以我想知道我在哪裏可以找到我需要知道的更遠的地方。

我目前知道,我需要知道的事情是:

  • 的指令集來使用。我有兩臺筆記本電腦可以開發;都有Core 2 Duo處理器。我目前的理解是,x86處理器大多使用相同的指令集,但它們並不完全相同。

  • 操作系統是否影響編譯的代碼生成步驟,或者它是否完全依賴於處理器。例如,我知道生成代碼在32位與64位平臺上運行的不同之處。

  • 如何組織棧幀等。何時使用寄存器與將參數放入堆棧,調用者保存與被調用者保存,所有這些。我一直認爲這將與指令集一起描述,但到目前爲止我還沒有在任何地方看到這個特定的信息。也許我在這裏誤解了一些東西?

以資源代替答案的鏈接非常受歡迎。

+0

投票結束太寬泛。 – 2015-10-01 12:20:18

回答

5

大多數x86指令集對於所有處理器都是通用的 - 這是一個合理安全的選擇,您的處理器都具有相同的指令集,除了SIMD指令可能對您不太有用實現一個簡單的編譯器(這些指令通常用於製作多媒體應用程序等等)。指令集在Intel's manuals中列出 - 2A和2B中特別列出了指令及其行爲,儘管其他卷值得關注。

當生成用戶空間代碼時,涉及到系統調用時操作系統的選擇很重要。舉例來說,如果你想有一個程序來輸出不同的是在終端上64位Linux,你需要做一個系統調用:

  • 裝載價值1到寄存器rax,表示這是一個write系統調用。
  • 裝載價值1到寄存器rdi,表示標準輸出應採用(1是標準輸出文件描述符)
  • 加載的要打印到寄存器rsi
  • 裝的是什麼,你長什麼的起始地址想要打印到寄存器rdx
  • 一旦寄存器(和存儲器)已經建立,就執行syscall指令。

write的返回值存儲在rax中。

不同的操作系統可能有不同的系統調用號爲write,可能在參數傳遞(x86-64的Linux系統調用始終使用rdirsirdxr10r8不同的方式,並在r9系統調用號碼爲rax),並可能完全不同的系統調用。

普通功能的約定在Linux上調用類似 - 寄存器的順序是rdirsirdxrcxr8r9(所以都是一樣的,但是使用了rcx代替r10),進一步論證在堆棧上並返回值爲rax。根據this page,寄存器rbp,rbxr12高達r15應保留跨功能調用。當然,你可以自由地構建自己的約定(除非進行系統調用),但是這使得從其他人生成或編寫的代碼中調用被調用更加困難。

+0

謝謝,邁克爾 - 這個答案也很有幫助。我希望我也能接受它;我自己的錯誤是要結合太多的問題。 +1,但。 – danben 2010-03-02 16:15:19

+0

其實,第二次閱讀這篇文章,我認爲這完全回答了我所有的問題。 – danben 2010-03-04 05:00:01

3

堆棧框架和 如何組織。何時使用寄存器與 將參數放在堆棧上, 調用者保存與被調用者保存,全部爲 。我一直以爲這將 與 指令集一起描述,但到目前爲止我沒有 在任何地方看到這個特定的信息。 也許我在誤解 這裏?

一般來說,這些問題沒有正確的答案。你可以使用你想要的任何調用約定......除非你想與其他人的代碼進行互操作。爲了實現互操作性,編譯器在應用程序二進制接口上進行標準化。我的理解是,Itanium C++ ABI近年來已成爲流行的標準。嘗試從那裏開始。

+0

謝謝,內森。我不太瞭解Itanium C++ ABI的目的,因爲它與我的目的有關(例如,C++在爲另一種語言開發編譯器時扮演了什麼角色?);然而,這個鏈接最終導致了我正在尋找的各種x86調用約定(cdecl等)。 – danben 2010-03-02 16:14:14

1

我無法回答你們所有的問題;但

  • 基本x86指令集是整個x86系列處理器 的 兼容。你不打算 實施任何具體的擴展, 你呢?
  • 我不認爲你的OS 或結構問題多的代碼 代
  • 默認答案相關 任何編譯器是 Dragon book。你有沒有看過 呢?