gcc g 命令使用及編譯原理二

2021-08-22 08:19:18 字數 3015 閱讀 6763

對於編譯原理,如果要系統的學習的話,知識點多的完全可以寫成一本書,推薦大家可以去閱讀一下《編譯原理》這本書,可以全面深入的學習編譯原理,很經典。接下來的文章我僅僅對gcc/g++編譯原理寫一些記錄。

其中gcc命令是對c語言檔案的編譯,g++命令是對c++檔案的編譯,其命令的原理其實是一樣的。

gcc命令編譯一般分為四個步驟及呼叫的命令:

先上乙個醜陋的概念圖

原始檔,以下是hello.c**

#includeint main()
預處理階段主要處理#include和#define,它把#include包含進來的.h 檔案插入到#include所在的位置,把源程式中使用到的用#define定義的巨集用實際的字串代替,刪除注釋。

執行命令,會生成hello.i檔案

$ gcc -e hello.c -o hello.i

# 1 "hello.c"

# 1 "/usr/include/stdio.h" 1 3 4

# 29 "/usr/include/stdio.h" 3 4

# 1 "/usr/include/_ansi.h" 1 3 4

# 10 "/usr/include/_ansi.h" 3 4

# 1 "/usr/include/newlib.h" 1 3 4

# 14 "/usr/include/newlib.h" 3 4

# 1 "/usr/include/_newlib_version.h" 1 3 4

# 15 "/usr/include/newlib.h" 2 3 4

# 11 "/usr/include/_ansi.h" 2 3 4

# 1 "/usr/include/sys/config.h" 1 3 4

# 1 "/usr/include/machine/ieeefp.h" 1 3 4

# 5 "/usr/include/sys/config.h" 2 3 4

# 1 "/usr/include/sys/features.h" 1 3 4

# 6 "/usr/include/sys/config.h" 2 3 4

# 234 "/usr/include/sys/config.h" 3 4

# 1 "/usr/include/cygwin/config.h" 1 3 4

# 235 "/usr/include/sys/config.h" 2 3 4

# 12 "/usr/include/_ansi.h" 2 3 4

# 30 "/usr/include/stdio.h" 2 3 4

.....此處忽略一千行

# 797 "/usr/include/stdio.h" 3 4

# 2 "hello.c" 2

# 3 "hello.c"

int main()

編譯階段首先檢查**的規範性,語法錯誤,最終把**翻譯成組合語言

執行命令:

$ gcc -s hello.i -o hello.s

以下是生成的hello.s彙編**,有興趣的同學可以研究一下,對於反彙編,這乙份**是必需看懂的^-^。

.file	"hello.c"

.text

.def __main; .scl 2; .type 32; .endef

.section .rdata,"dr"

.lc0:

.ascii "hello world!\0"

.text

.globl main

.def main; .scl 2; .type 32; .endef

.seh_proc main

main:

pushq %rbp

.seh_pushreg %rbp

movq %rsp, %rbp

.seh_setframe %rbp, 0

subq $32, %rsp

.seh_stackalloc 32

.seh_endprologue

call __main

leaq .lc0(%rip), %rcx

call printf

movl $0, %eax

addq $32, %rsp

popq %rbp

ret.seh_endproc

.ident "gcc: (gnu) 7.3.0"

.def printf; .scl 2; .type 32; .endef

彙編階段把hello.s檔案翻譯成二進位制機器指令,把hello.s檔案轉換成hello.o檔案,執行命令:

$ gcc -c hello.s -o hello.o

生成的檔案是二進位制格式,普通人是看不懂了,這是乙份讓機器理解的**

當然,我們也可以通過ida,od等工具反彙編得到彙編**

很多人都會認為到了彙編階段產出的.o檔案就可以使用了,當然這個想法是錯誤的,還需要最後乙個階段,就是鏈結階段(linking),可以通俗的理解為關聯系統的api,我們的程式呼叫stdio.h中的printf函式,而這個標準的列印函式是由系統提供的,而鏈結階段就是告訴我們應用呼叫prinft的地方,該去**呼叫這個函式的實現地方,有可能是系統的標準庫函式庫,也有可能是外面提供的函式庫,反正結果就是讓我們的應用知道在**去找到這個函式。

執行命令,最終生成hello可執行的檔案:

$ gcc hello.o -o hello

函式庫一般分為靜態庫和動態庫兩種

文章所有的例子**工程

Linux編譯器 gcc g 使用

gcc是乙個編譯器,將我們寫的高階語言轉化成機器語言 gcc如何完成 格式 gcc 選項 要編譯的檔案 選項 目標檔案 預處理 進行巨集替換 展開所有 gcc e 例 gcc e main.c o main.i o是重新命名,使main.c預處理後生成的檔案名叫main.i 編譯 生成彙編 糾錯,沒...

Linux編譯器 gcc g 使用

gcc 選項 要編譯的檔案 選項 目標檔案 預處理 進行巨集替換 在c語言程式中,並沒有printf函式的定義,stdio.h中也只有該函式的宣告,沒有該函式的實現。系統把這些函式的實現放到指定的庫檔案中例如 libc.so.6,gcc會到系統預設的路徑中進行查詢,這就是連線的作用 建立方法 將包包...

gcc g 命令的經常使用選項

gcc g 命令的經常使用選項格式 選項 解釋 o file 指定輸出檔名稱。在編譯為目標 時,這一選項不是必須的。假設file沒有指定,預設檔名稱是a.out.c 僅僅編譯生成目標檔案,不鏈結 m486 針對 486 進行 優化。o0 不進行優化處理。o 或 o1 優化生成 o2 進一步優化。o3...