我們編寫的程式**是怎樣執行起來的?到底執行的是什麼內容?平時我們所說的編譯主要包括預編譯、編譯、彙編與鏈結,這四部分分別都幹什麼工作,主要職能有哪些。
講述編譯之前,我們先要了解程式記憶體。乙個由c/c++編譯的程式占用的記憶體,大致分為以下幾個部分:
1、棧區(stack): 由編譯器自動分配釋放 ,存放函式的引數值,區域性變數的值等。其操作方式類似於資料結構中的棧。
2、堆區(heap): 一般由程式設計師分配釋放, 若程式設計師不釋放,程式結束時可能由os** 。
3、全域性區(靜態區)(static)
4、文字常量區:常量字串就是放在這裡的。 程式結束後由系統釋放
5、程式**區:存放函式體的二進位制**。
windows中以2:2劃分核心、使用者空間,linux中以1:3劃分核心、使用者空間。
圍繞著記憶體,編譯過程大概如下:
1.#define 巨集文本替換
2.#include 遞迴展開標頭檔案
3.#if #endif #elif 刪除預編譯指令
4.刪除注釋
5.新增行號和文字標識
6.保留 #pragma 編譯器處理
【編譯階段以乙個.cpp或者.c檔案為單元編譯】
1.詞法分析
2.語法分析
3.語義分析
4.**優化 生成彙編**
[inter x86]
//彙編**
int a =10;
mov dword ptr[a]
,0ah //ptr[a] 對a位址解引用後得到a的記憶體 //0ah 是10
可重定位(重入)的二進位制檔案
linux中elf檔案,bss段:段以符號起始,節省空間
bss段少了乙個資料,和虛擬位址空間上的段不同意義。 (bss段中少的資料,位於com塊中)
強弱符號:強符號是已初始化的全域性變數,弱符號是未初始化的全域性變數【c++中無強弱符號之分】
強弱符號規則:
1.兩強:重定義錯誤 //資料段不可以出現重名
2.一強一弱:選強符號作為所有位址
3.兩弱:選位元組數大的 《編譯器處理》
在彙編完成前,不清楚是否存在強符號無法判斷時,則將變數放入com塊中。
生成.exe檔案 也是elf檔案,有頭和.data、.text段等
//und 未定義區 //找不到
1.段合併:相同段合併《乙個段對映乙個頁面》
合併符號表:同名查詢,未找到則用本身查詢的弱符號,找到則刪除弱符號改用強符號
2.符號解析(處理und):未找到對應的符號進行報錯 合併und
3.分配位址和空間
4.符號的重定位 //test段 《虛假位址改真實,糾正虛假偏移》
鏈結**:[ld -e main -o run main.o sum.o]
【linux】中關於預編譯、編譯、彙編、鏈結的**
1.[預編譯] gcc -e aff.c -o main.i
[ls] aff.c main.i
2.[編譯]gcc -s main.i -o main.s
[ls]aff.c mian.i main.s
3.[彙編]gcc -c mian.s -o main.o
[ls]aff.c mian.i main.s main.o a.out
4.[鏈結]/a.out //此時是.exe檔案(可執行檔案)
預編譯,編譯,彙編,鏈結
2.編譯的工作內容 3.彙編的工作內容 4.鏈結器的工作內容 參考 include int main 使用gcc編譯器 gcc hello.c a.out a.out 含義是 assembler output 即 彙編輸出 上述過程可以分解為四個步驟 1.預處理 prepressing gcc e ...
C 預編譯 編譯 彙編 鏈結
windows中以2 2劃分核心 使用者空間,linux中以1 3劃分核心 使用者空間。在text段中,只有普通區域性變數是指令 int gdata1 10 data 已初始化且初始化不為零的資料 int gdata2 0 bss 未初始化或初始化為零的資料 int gdata3 bss stati...
預編譯,編譯,鏈結的原理
假設我們有下面這樣的乙個程式,源 如下 main.c include mytool1.h include mytool2.h int main int argc,char argv mytool1.h ifndef mytool 1 h define mytool 1 h void mytool1 ...