Saturday, July 23, 2011

編譯器與連結器的基本概念

編譯器與連結器的基本概念

C/C++ 語言的特性
作業系統如何執行一個程式
編譯器的工作

"一個程式所呼叫的函式可能在另一個原始碼檔案(.c 或 .cpp)當中,也可能在另一個機械碼檔案(.obj)中,也可能在程式庫檔案中(.lib)中,無論如何,當編譯器在編譯 HelloWorld.cpp 的時候它並不知道 printf( ) 的程式碼在哪裡,亦不知道程式的流程該跳往何位址,所以在編譯出的 .obj 檔案中這個「空格」會被保留下來,而由連結器(linker)收集了所有的機械碼檔案(.obj與.lib)以後,才將它們填上,其實程式庫檔案(.lib)只不過是一些機械碼檔案(.obj)的集合體。

承續上面的例子,如下圖所示,連結器所產出的可執行檔(executable file)裡面,它把 HelloWorld.obj 和 printf( ) 的機械碼都合併 HelloWorld.exe 當中了,所以在 HelloWorld.obj 當中呼叫 printf( )函式所造成的程式流程跳躍(jump),就變成了是同一個 .exe 檔案內(作業系統載入後是同一塊記憶體內)的位址跳躍了,所以連結器可以明確地寫上位址數值,總結地來說連結器所做的事情就是收集像這樣互相參考的機械碼、合併為執行檔、並且填寫這些機械碼之間的參考位址,這就是為甚麼通常由原始碼產生的可執行檔都會比原始檔案大很多,因為合併了許多來其他檔案的機械碼。

作業系統載入一個可執行檔的時候,它只會配置該程式的專屬記憶體,並且把可執行檔載入到記憶體當中,並從其中某個位置開始執行程式,所有該程式需要的一切,都必須已經在 .exe 檔案裡面,所以由原始碼產生執行檔的過程中,除了要編譯(compile)還需要經過連結(link)才能得到這樣的可執行檔。"


.

No comments:

Post a Comment