鏈接的基本概念

什麼是鏈接

鏈接是將各種代碼和數據片段收集並組合成爲單一文件的過程

編譯器驅動程序

int sum(int *a,int n);

int array[2]={1,2};

int main(){
    int val=sum(array,2);
    return val;
}

main.c

int sum(int *a,int n){
    int i,s=0;
    for(i=0;i<n;i++){
        s+=a[i];
    }
    return s;
}

sum.c

我們可以通過下面的語句來調用gcc驅動程序

$ gcc -Og -o prog main.c sum.c

??這裏我不知道怎麼用-v 來查看步驟

我們可以來看一下這個過程(那main.c來說)

首先:

預處理器(cpp)將main.c翻譯成一個ascII碼的中間文件main.i:

cpp [other arguments] main.c /tmp/main.i

接下來,驅動程序運行c編譯器(cc1)將main.i->main.s(ascll彙編語言文件)

cc1 /tmp/main.i -Og[other arguments ] -o /tmp/main.s

然後運行彙編器(as)將main.s轉爲main.o(可重定位目標文件)

as [other argument ] -o /tmp/main.o /tmp/main.s

最後運行連接器(ld),將main.o和sum.o和有關代碼組合起來,形成一個可執行目標文件

ld -o prog [system object files and args] /tmp/main.o /tmp/sum.o

鏈接的主要任務

符號解析

將符號定義與引用對應起來

比如想上面的main.o和sum.o鏈接的過程中,鏈接器就得將main.o中對sum的引用與sum.o中的sum的定義對應起來。

這裏的符號可以是一個函數,一個全局變量,一個靜態變量

思考:這裏爲什麼沒有提到局部變量

重定位

因爲我們的鏈接器和彙編器生成的是從0字節開始的代碼段,鏈接器首先對把每一個符號定義與一個具體的內存位置關聯起來,從而重定位這些節,然後修改所有對這些符號的引用,使他們指向這個內存位置,

目標文件

可重定位目標文件

包含二進制代碼和數據,其形式可以在編譯時與其他可重定位目標文件合併起來

可執行目標文件

包含二進制,代碼和數據,其形式可以被直接複製到內存並執行

共享目標文件:

一種特殊類型的可重定位目標文件,可以在加載或者運行時被動態加載進內存並鏈接

注:一般各個系統的可執行文都不同,老版unix 使用的是a.out,windows 使用的是可移植可執行的pe格式,現代linux 和unix 是ELF格式

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章