假設有乙個hello.c
程式,**如下:
#include int main()
我們在unix
系統中編譯
gcc -o hello hello.c
編譯後執行./hello
,就能看到結果了。
當我們在系統上編譯hello
程式時,系統做了些什麼?
hello
程式的生命週期是從乙個高階c語言程式開始的,因為這種形式能夠被人讀懂。然而,為了在系統上執行hello.c
程式,每條c語句都必須被其他程式轉化為一系列的低階機器語言指令。然後這些指令按照一種稱為可執行目標程式的格式打好包,並以二進位制磁碟檔案的形式存放起來。目標程式也稱為可執行目標檔案。
在unix
系統上,從原始檔到目標檔案的轉化是由編譯器驅動程式完成的:
在這裡, gcc編譯器驅動程式讀取源程式檔案hello.c
,並把它翻譯成乙個可執行目標檔案hello
。這個翻譯過程可分為四個階段完成,如圖所示。執行這四個階段的程式(預處理器、編譯器 、彙編器和鏈結器)一起構成了編譯系統(compilation system)。
預處理階段:預處理器(cpp)根據以字元#開頭的命令,修改原始的c程式。比如hello.c
中第1行的#include
命令告 訴預處理器讀取系統標頭檔案stdio.h
的內容,並把它直接插入 程式文字中。結果就得到了另乙個c程式,通常是以.i
作為副檔名。
編譯階段:編譯器(ccl) 將文字檔案hello.i
翻譯成文字檔案hello.s
,它包含乙個組合語言程式。該程式包含函式main
的定義。
在命令列上使用「-s」選項,就能看到c語言編譯器產生的彙編**,這會使gcc執行編譯器,產生乙個彙編檔案hello.s
,但是不做其他進一步的工作。
彙編階段:接下來,彙編器(as)將hello.s
翻譯成機器語言指令,把這些指令打包成一種叫做可重定位目標程式 (relocatable object program) 的格式,並將結果儲存在目標檔案hello.o
中。hello.o
檔案是乙個二進位制檔案,它包含的 17個位元組是函式main
的指令編碼。如果我們在文字編輯器中開啟hello.o
檔案,將看到一堆亂碼。
如果我們使用 「-c」 命令列選項,gcc會編譯並彙編該**:這就會產生目標**檔案hello.o
, 它是二進位制格式的,所以無法直接檢視。
在linux
系統中,帶 『-d』 命令列標誌的程式objdump
(表示 「object dump」)可以充當這個角色:
鏈結階段:請注意,hello
程式呼叫了printf
函式,它是每個c編譯器都提供的標準c庫中的乙個函式。printf
函式存在於乙個名為printf.o
的單獨的預編譯好了的目標檔案中,而這個檔案必須以某種方式合併到我們的hello.o
程式中。鏈結器(id)就負責處理這種合併。結果就得到hello
檔案,它是乙個可執行目標檔案(或者簡稱為可執行檔案),可以被載入到記憶體中,由系統執行。
gcc -o hello hello.c
深入理解計算機系統
關鍵路徑是在迴圈的反覆執行中形成的資料相關鏈。迴圈展開是一種程式變換,通過增加每次迭代計算的元素的數量,減少迴圈的迭代次數。重新結合變換能夠減少計算中關鍵路徑上操作的數量,通過更好地利用功能單元的流水線能力得到更好的效能。浮點運算不保證是可結合的,通常迴圈展開和並行地累積在多個值中,是提高程式效能的...
《深入理解計算機系統》
知乎 深入理解計算機系統 這本書需要什麼水平能看懂?15 213 18 218 15 513 introduction to computer systems schedule fall 2016 鏈結失效則 cmu15 213的課程主頁,有ppt,還有錄影,主講人就是這本書的作者。備註 備註 詳細...
深入理解計算機系統
系統的硬體組成 快取記憶體 作業系統管理硬體 程序虛擬記憶體 檔案amdahl定律 併發和並行 0和1組成的位序列,又稱為位元序列,8個位被組織成一組,成為位元組。每個位元組表示程式中的某些文字字元。系統中的所有資訊 包括磁碟檔案 記憶體中的程式 記憶體中存放的的使用者資料以及網路上傳送的資料,都是...