編譯鏈接過程

csdn地址:《程序員的自我修養》讀書筆記-編譯鏈接過程

準備

對于入門的hello world程序, 如下所示:

#include <stdio.h>
int main()
  {
    printf("hello world\n");
    return 0;
  }

在IDE中僅需點擊一下運行既可看到程序的運行結果,而如果使用GCC編譯,也非常簡單,只需gcc hello.c即可生成目標文件a.out, 但其中隱藏了編譯鏈接的基本步驟,分別為:預處理、編譯、匯編和鏈接。通過

gcc  --verbose hello.c -o a.out

可看到各步驟的流程。

預處理

預處理過程主要處理源碼中以“#”開始的預編譯指令, 比如“#include"、“define"等。通過預處理后的輸出文件后綴為.i 或者.ii, 具體實現預處理過程的為預編譯器cpp。若要查看預處理后的文件,可用:

gcc -E hello.c -o hello.i
或者:cpp hello.c > hello.i
  • 主要處理規則:

1. 刪除所有的#define, 并展開所有的宏定義;
2. 處理所有的條件預編譯指令,如#if、#ifdef等;
3. 處理“#include"預編譯指令;
4. 刪除所有注釋;
5. 添加行數和文件名標識;

  • 舉例說明:

例如定義常量 CONST_TEST,如下:

#include <stdio.h>
#define CONST_TEST 5
int main()
{
    printf("%d\n", CONST_TEST);
    return 0;
}

在經過預處理后main函數變成如下:

int main()
{
    printf("%d\n", 5);
    return 0;
}

編譯

編譯過程就是把預處理完的文件進行一系列詞法分析、語法分析、語義分析以及優化后生成相應的匯編代碼文件。gcc命令如下:

gcc -S hello.i -o hello.s
或者:ccl hello.c
備注:對于c語言來說, 預處理和編譯的實現程序為ccl, c++對應的程序為cclplus。

生成的hello.s文件為:

    .section    __TEXT,__text,regular,pure_instructions
    .macosx_version_min 10, 12
    .globl  _main
    .align  4, 0x90
_main:                                  ## @main
    .cfi_startproc
## BB#0:
    pushq   %rbp
Ltmp0:
    .cfi_def_cfa_offset 16
Ltmp1:
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
Ltmp2:
    .cfi_def_cfa_register %rbp
    subq    $16, %rsp
    leaq    L_.str(%rip), %rdi
    movl    $0, -4(%rbp)
    movb    $0, %al
    callq   _printf
    movl    $1, %ecx
    movl    %eax, -8(%rbp)          ## 4-byte Spill
    movl    %ecx, %eax
    addq    $16, %rsp
    popq    %rbp
    retq
    .cfi_endproc

    .section    __TEXT,__cstring,cstring_literals
L_.str:                                 ## @.str
    .asciz  "hello world\n"


.subsections_via_symbols

匯編

匯編過程主要是將匯編代碼轉變成機器可以執行的指令, 生成目標文件。gcc命令為:

gcc -c hello.s -o hello.o
或者:as hello.s -o hello.o

鏈接

通過匯編過程生成的目標文件并不能直接執行,其原因包括:某個源文件中的函數可能引用了另一個源文件中定義的某個符號(如變量或者函數調用等);在程序中可能調用了某個庫文件中的函數等, 而鏈接就是解決這些問題。鏈接程序的主要工作就是將有關的目標文件彼此相連接,也即將在一個文件中引用的符號同該符號在另外一個文件中的定義連接起來,使得所有的這些目標文件成為一個能夠按操作系統裝入執行的統一整體。鏈接命令為ld,對于上訴的hello wrold程序,可用:

ld -demangle -dynamic -arch x86_64 -macosx_version_min 10.12.0 -syslibroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk -o hello.out hello.o  -lSystem /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/8.0.0/lib/darwin/libclang_rt.osx.a

備注:測試環境為mac 10.12.3 (16D32)。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容