預編譯,編譯,彙編,鏈結

2021-10-04 12:03:50 字數 1777 閱讀 4496

2. 編譯的工作內容

3. 彙編的工作內容

4. 鏈結器的工作內容

參考

#include int main()

使用gcc編譯器:

gcc hello.c

./a.out

a.out 含義是 assembler output 即 彙編輸出

上述過程可以分解為四個步驟:

1. 預處理(prepressing) gcc -e hello.c 生成 xx.i檔案

2. 編譯(compilation) gcc -s xx.i 生成 xx.s

3. 彙編(assembly) gcc -c xx.s 生成 xx.o

5. 鏈結(linking) gcc xx.o 生成 a.out

gcc -e hello.c -o hello.i

預編譯過程主要處理那些原始檔中以「#」開始的預編譯指令

比如:#include #define #if #ifdef

編譯器就是將高階語言翻譯成機器語言的乙個工具。

1. 將所有的#define 刪除,並且展開所有的巨集定義

2. 處理所有條件編譯指令,如#if #ifdef #elif #else #endif

3. 處理#include預編譯指令,將包含的檔案插入到該預編譯指令的位置,這個過程是遞迴進行的。

4. 刪除所有的注釋 // 和 /**/

5. 新增行號和檔名標識,比如 #2 hello.c 2 ,以便除錯資訊,錯誤,告警等顯示行號

6. 保留所有的#pragma等編譯器指令,因為編譯器需要他們

結果:經過預編譯後的hello.i檔案不包含任何巨集定義,因為所有的巨集已經被展開。

gcc -s hello.i -o hello.s

編譯過程:編譯過程一般可以分為6步:掃瞄、詞法分析,語法分析,語義分析、源**優化、**生成、目標**優化。

1. 掃瞄:首先源**被輸入到掃瞄器(scanner)

2. 詞法分析:將源**的字串行分割成一系列的記號

記號分為: 關鍵字,識別符號,字面量(數字字串),特殊符號

3. 語法分析:對記號進行語法分析,產生語法樹(syntax tree),就是以表示式為節點的樹

4. 語義分析:給語法樹的表示式標識型別

5. 中間語言生成:簡單的**優化,如 4+5 直接計算結果

6. 目標**生成與優化:選擇合適的定址方式、使用位移來代替乘法運算、刪除多餘的指令等

後面將圖貼上來!

gcc -c hello.s -o hello.o

彙編:將彙編**轉變成機器可以執行的**指令,每乙個彙編語句幾乎都對應一條機器指令。

重定位(relocation):重新計算各個目標的位址過程叫做重定位(relocation)

符號(symbol):表示乙個位址,這個位址可以是一段子程式/函式,也可以是乙個變數的起始位址。

模組之間的呼叫歸結為如何通訊的問題,常見是模組間的函式呼叫和模組間的變數訪問。

模組的拼接的過程就是鏈結

鏈結(linking):主要內容就是把各個模組之間的相互引用的部分都處理好,使得各個模組之間能夠正確的銜接。

鏈結的主要過程:包括位址和空間分配,符號決議,重定位

庫:其實是一組目標檔案的包,就是一些最常用的**編譯成的目標檔案後打包存放。

執行時庫(running library):它是支援程式執行的基本函式的集合

詳細參考之前的部落格

C 預編譯 編譯 彙編 鏈結

windows中以2 2劃分核心 使用者空間,linux中以1 3劃分核心 使用者空間。在text段中,只有普通區域性變數是指令 int gdata1 10 data 已初始化且初始化不為零的資料 int gdata2 0 bss 未初始化或初始化為零的資料 int gdata3 bss stati...

編譯原理 預編譯 編譯 彙編與鏈結

我們編寫的程式 是怎樣執行起來的?到底執行的是什麼內容?平時我們所說的編譯主要包括預編譯 編譯 彙編與鏈結,這四部分分別都幹什麼工作,主要職能有哪些。講述編譯之前,我們先要了解程式記憶體。乙個由c c 編譯的程式占用的記憶體,大致分為以下幾個部分 1 棧區 stack 由編譯器自動分配釋放 存放函式...

預編譯 編譯 彙編 鏈結過程

將源 或者標頭檔案經過預編譯成乙個.i檔案。例如c 副檔名是.cpp,標頭檔案的副檔名可能是.hpp,預編譯後的副檔名是.i 預編譯的過程相當於下面的命令 對c語言檔案的處理 gcc e 原始檔 o目標檔案 對c 語言的檔案的處理 g gcc e 原始檔 o目標檔案 例如 gcc e hello.c...