1. 程式人生 > >理解編譯器在編譯過程中做了什麼

理解編譯器在編譯過程中做了什麼

今年開了作業系統課,課上老師提了一個問題:從一個儲存程式程式碼的文字檔案到可執行的程式,編譯器做了啥?由於之前買過<<深入瞭解計算機系統>>這本書,剛買來時受熱就翻了其中一部分章節,其中就有講到上述所問的講解,索性就參考其上的講解寫出來

我會以一個hello.c的c程式貫穿整個文章,具體程式碼如下

#include<stdio.h>

int main(int argc,char **argv)
{
    printf("hello world\n");
    return 0;
}

該程式通過編譯器編譯生成hello程式,其執行結果如下

那麼此程式從儲存它的文字檔案到可執行程式hello的中間編譯器究竟做了啥,不說話先上圖了



由上圖可知gcc編譯器驅動程式在讀取了hello.c檔案之後,把它翻譯成了一個可執行程式碼。此過程共經歷了4個階段的程式,分別是前處理器,編譯器,彙編器,連結器,此4個截斷程式一起構成了編譯系統。接下來我就為大家詳細說明以下此4個階段程式各自的具體工作

1.預處理階段

前處理器會將以字元#開頭的語句,修改為原始的c程式,比如hello.c中的#include

gcc -E hello.c -o hello.i

用vim開啟hello.i檔案之後如下圖
這是檔案開頭

這是檔案結尾處

我想大家一定會驚訝的發現一個簡簡單單的hello,world程式竟然會平白無辜的增加了800多行,沒錯這就是前處理器乾的,它將程式中以#開頭的stdio.h檔案的內容都加了進來
需要強調的是,經前處理器的檔案是文字檔案

2.編譯器

編譯器會將上文中提到的hello.i(預編譯好的檔案)近一步翻譯成儲存組合語言的文字,其後綴會變為.s
我們可以通過如下方式將hello.c編譯成.s檔案

gcc -S hello.c -o hello.s

開啟hello.s檔案如下圖

可以看到裡面的程式碼變為了彙編程式碼
需要注意的是.s檔案依然是文字檔案

3.彙編器

彙編器會將上述的hello.s檔案翻譯成機器語言指令,並把這些指令打包成一種叫做可重定位目標程式的格式並將結果儲存在新生成的二進位制檔案hello.o中

4.連結階

我們的程式hello中呼叫了printf函式,而printf函式存在於由c標準庫提供的名為printf.o的單獨預編譯好了的目標檔案中,所以我們要呼叫printf函式,就得通過連結器,使其通過它自己的方式將hello.o和printf.o這倆個檔案合併在一起,經過合併後的檔案就是可執行的hello檔案了

相關推薦

理解編譯器編譯過程什麼

今年開了作業系統課,課上老師提了一個問題:從一個儲存程式程式碼的文字檔案到可執行的程式,編譯器做了啥?由於之前買過<<深入瞭解計算機系統>>這本書,剛買來時受熱就翻了其中一部分章節,其中就有講到上述所問的講解,索性就參考其上的講解寫出來

oracle的commit過程什麼

    oracle中的commit過程速度快,預設情況下同步操作,當然也可以選擇非同步。     commit過程中大致做了四件事情:     1.產生SCN。     2.等待LGWR將餘下的日誌緩衝資料寫線上重做日誌,並將SCN寫入日誌,到此事務基本上結束了,查詢V$

創建一個對象都在內存什麽事情

什麽 分配 首地址 位置 內存 一個 new class文件 class 創建一個對象都在內存中做了什麽事情? 1:先將硬盤上指定位置的Person.class文件加載進內存。 2:執行main方法時,在棧內存中開辟了main方法的空間(壓棧-進棧),然後在main方法的棧

【轉】C 編譯器優化過程的 Bug

你是 should 有一個 avi return 們的 團隊 ref 似的 一個朋友向我指出一個最近他們發現的 GCC 編譯器優化過程(加上 -O3 選項)裏的 bug,導致他們的產品出現非常詭異的行為。這使我想起以前見過的一個 GCC bug。當時很多人死活認為那種做法是

Java面試題系列(三)Java new一個對象的過程發生什麽

進行 col over mage 兩個 http system jvm art Person class Person{ private String name; private int age; public Person(

一個頁面從輸入URL到頁面加載顯示完成,這個過程發生什麽?

域名服務器 tex -type 發送請求 頁面加載 異步 htm dns查詢 tcp 1.瀏覽器通過DNS查找域名對應的IP地址(DNS查詢:瀏覽器緩存-->系統緩存-->路由器緩存-->ISP DNS 緩存 -->根域名服務器) 2.瀏覽器向Web

String str = new String("content") 建構函式有沒有返回值?new關鍵字到底在物件初始化什麼?

看到String str = new String("content")時想到一個問題:在我印象裡,建構函式時沒有返回值的,那麼建立的物件是如何賦值的呢?有沒有方法確定知道建構函式有沒有返回呢? 建構函式時沒有返回值的,賦值因為new關鍵字。 new的內部是呼叫了一個叫void * oper

JVM調優——Java動態編譯過程的記憶體溢位問題

由於測試環境專案每2小時記憶體就溢位一次, 分析問題,發現Java動態載入Class並執行那塊存在記憶體溢位問題, 遂本地調測。 一、找到動態編譯那塊的程式碼,具體如下 /** * @MethodName : 編譯java程式碼到Object * @Descrip

myeclipse安裝反編譯器jad過程Java不顯示jadclipse

myeclipse中安裝反編譯器jad過程中Java不顯示[email protected]TOC 基本上按照https://www.cnblogs.com/hdk1993/p/4555730.html這篇部落格上操作就可以成功安裝 如果不行的話,可以嘗試https://zhida

記錄反編譯過程遇到的問題

1.反編譯過程中遇到如下異常: I: Baksmaling... I: Loading resource table... Exception in thread "main" brut.androlib.AndrolibException: Could not de

Ant編譯過程出現錯誤:找不到符號

Ant進行javac編譯時,如果出現找不到符號的錯誤,則可能是缺少類路徑,則需要配置依賴的jar包,使用Ant<classpath>的標籤,載入依賴的jar包。 如圖所示: 但是我遇到的

Oprofile編譯過程出錯解決辦法

“liberty library not found” error when configuring Oprofile 解決辦法: $sudo apt-get install libiberty-dev     “bfd library not found”

bitcoind編譯過程的問題

本文列出個人在編譯比特幣程式bitcoind以及啟動執行中遇到的問題。 1 執行autogen.sh libtool沒有安裝 Makefile.am:10: error: Libtool library used but 'LIBTOOL' is undefined Ma

使用node過程出現亂碼

使用node搭建了一個簡單的伺服器,當使用form提交資料後,伺服器給返回的資訊成亂碼了,html頁面中已經使用了charset,處理的方法是:把html頁面重新設定一下charset,重新儲存一下就好了

String str = new String("content") 建構函式有沒有返回值?new關鍵字到底在物件初始化什麼?

看到String str = new String("content")時想到一個問題:在我印象裡,建構函式時沒有返回值的,那麼建立的物件是如何賦值的呢?有沒有方法確定知道建構函式有沒有返回呢? 建構函式時沒有返回值的,賦值因為new關鍵字。 new的內部是呼叫了一個叫v

Spring容器初始化過程哪些事兒

1.ClassPathXmlApplicationContext為入口構造方法中有個refresh()方法用來初始化Spring refresh執行的大致流程: Configurab

編譯過程,報failed to resolve:com.andriod.databinding.adapters:1.1

菜鳥的部落格    failed to resolve:com.andriod.databinding.adapters:1.1 Error: Open file    Show in Project Structure dialog 我當時的解決方案 更新或下載

檔案系統編譯過程遇到問題,解決過程Kernel panic

用4.4.3 編譯器編譯出來的檔案系統 Empty flash at 0x0214bf7c ends at 0x0214c000 Empty flash at 0x0214fffc ends at 0x02150000 Empty flash at 0x02153fa0

gradle:編譯過程修改第三方jar包

編譯過程中修改第三方jar包 背景 Android專案過程中要引入第三方開源的jar,根據需求又要對其進行破壞性的定製,不修改原始碼不行。然而種種規範和要求又不能讓我們將第三方原始碼全部拿過來再修改。 奇葩的需求和奇葩的硬性規範,導致如下難題: 工程

如何找到自動化測試的思路和理解自動化測試過程的問題

    要找到自動化測試的思路,首先得明確自動化測試的本質。對自動化測試的本質的理解不同,導致了在進行自動化測試過程中對於組建團隊、制定目標計劃等的不同,決定了最終自動化測試的實施和效果的不同。所以必須先把自動化測試的本質說明白。     談本質的問題,每個人的理解是不盡相