1. 程式人生 > >編譯連結原理(二)——編譯階段

編譯連結原理(二)——編譯階段

       一、.o檔案

        編譯階段經過預編譯、編譯和彙編處理後生成一個.o檔案(以Linux系統為例),又編譯器編譯原始碼後生成的檔案叫做目標檔案。則目標檔案就是原始碼編譯後但未進行連線的那些中間檔案(windows下的.obj和Linux下的.o),它跟可執行檔案的內容和結構很相似,所以一般和可執行檔案採用同一種格式儲存。也就是從結構上來說,目標檔案是已經變異後的可執行檔案,知識沒有經過連結階段,其中有些符號或者地址沒有被調整。

       二、目標檔案的內容以及存放

        那麼目標檔案中至少有編譯後的機器指令程式碼、資料。當然,除了這些內容外,目標檔案中還包含了連結時所需要的一些資訊,例如符號表、除錯資訊、字串等。一般目標檔案將這些資訊按照不同的屬性按“段”的形式進行儲存。程式原始碼編譯後的機器指令經常被放在程式碼段裡,即“.text”中。全域性變數和區域性靜態變數資料經常放在資料段,即".data"中。未初始化的全域性變數和區域性靜態變數放在.bss段中。

        四、.bss段

        .bss段儲存的是未定義的全域性變數和區域性靜態變數。但.bss段只是為未初始化的全域性變數和區域性靜態變數預留位置而已,他並沒有內容,所以他在檔案中也不佔據空間。在這裡我們引入強弱符號(c語言中,只關心全域性變數)的概念:

        強符號:已初始化的全域性變數;

        弱符號:未初始化的全域性變數;

        強弱符號的使用規則:

  1. 兩強符號:重定義錯誤
  2. 一強一弱符號:選擇強符號
  3. 兩弱符號:選取位元組數較大的

        三、指令段和資料段

        在編譯階段結束會,生成可重定位的二進位制檔案即目標檔案,將檔案中的指令資料等資訊分別按照屬性儲存在虛擬地址空間中,資料區域對程序來說是可讀寫的,而指令段對與程序而言只是可讀的,所以這兩個區域的許可權是可讀寫和只讀。這樣就會防止指令被有意無意的篡改,同時當程式執行多個該程式的副本時,它們的指令是相同的,所以記憶體中只須要儲存一份該程式的指令部分。並且分開儲存有利於提高CPU的快取命中率。 

        4G的虛擬地址空間如圖所示: