編譯器如何得到內存空間?
01-28
請教一下編譯器後端的問題,前端那些我覺得學習的比較清晰了。符號表,運行時刻這些感覺理解的還可以。就是生產彙編代碼這裡,因為編譯的時候有代碼段數據段,肯定得申請一塊能用的內存區域。我就是不是很清楚這裡,我如何申請到一塊我能用的內存空間,又如何把代碼和數據放到相應的內存中呢?
這裡學的實在不去清楚,還希望大家能指點迷津。
申請空間然後把代碼放進去的這個事情是操作系統乾的,然後彙編本身有很多相對地址的處理方法,可以彌補這個空缺。然後「常量空間」的地址是可以寫死的,堆棧的空間則可以用ebp/esp獲得。所以這些都不是問題。
如果你一定要完全明白這個過程的話,得看intel的編程手冊。
http://msdn.microsoft.com/en-us/windows/hardware/gg463119.aspx
- 編譯和運行期的載入是兩回事;載入是載入二進位格式 (Comparison of executable file formats )(PE或者elf或者其他),操作系統載入的時候會把不同的數據段載入到不同的內存里。
- 對應彙編編譯器,直接生成的就是二進位格式。
- 對應生成彙編的編譯器,那當然要看對應彙編語言的語法了。基本的來講,不同的類型的數據(代碼或者數據)要放在不同的section placement里。看看x86的hello world: x86 assembly language。最後在鏈接器裡面,通過鏈接腳本指定各section的不同地址位置以及其他設置(一般嵌入式開發才會用到)。
如果想了解細節,可以看《程序員的自我修養》
基於我的理解 您是問編譯器是怎麼為製品劃分空間的?嘗試回答一下。首先,為製品獲取虛擬內存地址是鏈接器的工作。分靜態鏈接和動態鏈接兩種情況簡單討論。當熟悉了符號表和重定位表以後不難理解靜態鏈接是如何劃分虛擬地址空間的。簡單計算偏移就可以了吧?動態鏈接當使用類似靜態重定向方法來做的時候,和靜態鏈接類似。涉及到當代碼地址無關的的時候,使用got處理相關符號地址。上述是鏈接過程獲取內存地址的方法。當製品獲取以後,分配內存空間是裝載的工作。對於靜態鏈接的製品來說,直接裝載。對於動態鏈接的製品,由操作系統委託動態連接器裝載。我是不是跑題了?。。
編譯器簡單來說就是讀入位元組流處理後輸出位元組流的程序,不用想的太複雜,雖然從讀入位元組流變換到輸出位元組流的過程比較複雜,但本質不會改變。
就像頂樓所說的,程序載入和內存分配是操作系統的事,編譯器只要按預定好的格式(PE,ELF之類的)輸出文件就好。
代碼段數據段什麼的,寫到目標文件指定的位置就可以了吧。
推薦閱讀:
※PEG.js中如何消除左遞歸?
※專業書籍,應該怎樣筆記?怎樣看?
※Parser Combinator 在語法解析的當中處於怎樣的位置?
※基於中間代碼的優化中 循環的查找演算法有哪些呢 循環的優化方法又有哪些?
※KLEE到底是靜態分析工具還是動態分析工具?