.c/.cpp檔案 ->.exe檔案
需要經過 預編譯 編譯 彙編 鏈結
虛擬記憶體空間:
分為:約128m:0x08048000
.text 段:儲存**(指令)
.data段: 資料段(儲存所有的已初始化的全域性變數和所有區域性變數)
.bss段: 儲存未初始化的全域性變數(不占用空間,內容儲存在.comment段)
。。。其他字段(初始8個,還有可能有更多的)
間隔共享庫區:dll檔案等
間隔命令列引數:
環境變數
核心空間(不允許訪問:linux:1:3,windows:2:2)0xc000 0000
0xffff ffff
命令列引數:
main函式引數:
int main(int argc,char* argv,char env)
傳參舉例: ./a.out "hello"
int argc:引數個數
char* argv:字串陣列,給main函式傳入的字串陣列
char* env:傳入的環境變數,如「path=c:/dos
./c 或 .cpp:
經過 預編譯 ->.i 檔案
1.把#define 替換
2.把#include展開
3.把#if #endif #elseif 去除
4.刪除注釋
5.新增行號
6.保留#pragma(編譯)
編譯-> .s檔案
1.詞法分析
2.語法分析
3.語義分析(是否有歧義)
4.**優化(簡化)
彙編-> .o檔案 彙編指令**翻譯成二進位制
鏈結-> .exe檔案
1.合併段和符號表
2.符號解析
3.分配位址和空間(原來沒有位址的分配位址)
4.符號的重定位(強弱符號的選取)
linux:elf格式檔案
window :pe格式檔案
每個.c/.cpp檔案:
elf header
.text
.data
(為了和實位址相對應)
強弱符號:
強符號:已初始化的全域性變數
弱符號:未初始化的全域性變數
強弱符號的規則
1.兩強:重定義(報錯)
2.一強一弱:選強
3.兩弱:(看編譯器:任選乙個或者報錯)
int gdata1 = 10;//.data 已初始化 且 初始化不為零的資料
int gdata2 = 10;//.bss 未初始化 或 初始化不為零的資料
int gdata3; //.bss
static int gdata4 = 20; //.data
static int gdata5 = 0; //.bss
static int gdata6; //.bss
c語言下:int main()
main.c
test.c:#includeshort a = 10;
short b = 20;
extern fun();
int main()
如果沒有邊界控制:
結果會列印a = 30和b = 0;int a;
void fun()
在符號重定位的時候會判斷強弱符號,結果合併為short型別的符號,但在鏈結之前的test.c編譯過程中,編譯器認為a為int型別,賦給a的位址乙個4位元組的30;在鏈結後,仍然賦給a 4位元組的30,但接受時的a已經為兩位元組的資料了,所以賦值越位了,把下面的2位元組b的值給覆蓋成0。
靜態鏈結 編譯和鏈結(一)
彙編鏈結 小結本文主要是 程式設計師的自我修養 一書的內容摘要和梳理,如有需要並且沒有被本文涵蓋的內容,建議讀者自行 原書。靜態鏈結 目標檔案 二 靜態鏈結 靜態鏈結 三 裝載與動態鏈結 裝載與程序 一 裝載與動態鏈結 動態鏈結 二 本部分主要是介紹關於程式源 是如何到可執行檔案的,及這其中涉及到的...
編譯和鏈結 一
先從乙個最簡單的案例入手 helloworld.c,這裡我就不寫了,大家都寫過,我把它編譯成可執行程式gcc o helloworld helloworld.c 預處理 將所有的巨集定義替換 include檔案展開 刪除所有的注釋 新增行號和檔名標示 當然還有保留 pragma編譯指令等 編譯 把檔...
編譯鏈結過程(一)
什麼是編譯?什麼是鏈結?為什麼需要編譯和鏈結?在很久以前,計算機發展的初期,還在用機器語言編寫程式,量比較少時是不需要編譯和鏈結的。因為當時的程式設計師直接編寫機器碼讓計算機執行。每種cpu的指令是不相同的,所以每乙個程式要換一台不同cpu的機器上執行時,需要重新寫程式,而且機器語言 涉及很多計算機...