Linux Cプログラムの前処理、コンパイル、アセンブリ、リンクおよび実行プロセス

4087 ワード

Linux Cプログラムの前処理、コンパイル、アセンブリ、リンクおよび実行プロセス
  • Hello Wordプログラム直接コンパイル実行プロセス
  • 前処理
  • コンパイル
  • アセンブリ
  • リンク
  • 運転
  • Hello Wordプログラム直接コンパイル実行プロセス
    Linuxシステムの下で、任意のディレクトリ内に簡単なCプログラムを作成し、helloと名付けた.c、そのコードは以下の通りである.
      1 #include 
      2 int main(){
      3   //      
      4   printf("Hello Word
    "); 5 return 0; 6 }

    コードをコンパイルし、実行可能ファイルa.outを生成する:
    XXXX@ubuntu:~/hello$ gcc hello.c
    XXXX@ubuntu:~/hello$ ls
    a.out  hello.c
    

    実行可能ファイルa.outを実行し、結果を生成します.
    XXXX@ubuntu:~/hello$ ./a.out
    Hello Word
    

    以上は1つのプログラムが最も簡単で、最も迅速なコンパイル運転方式であるが、実際には、プログラムがコードから機械が実行可能な過程に至るまで、前処理、コンパイル、アセンブリ、リンク、運行などの過程に関連し、これらの過程を理解する必要がある.
    プリプロセッシング
    上のプログラムについてc前処理プロセスを行い、通常は以下の操作を行う:1、プログラム内の注釈内容を削除する;2.ヘッダファイルの内容を前処理指令位置にコピーする.
    はい==です.c==ファイルの前処理は、以下の方法で行うことができる.
    XXXX@ubuntu:~/hello$ gcc -E hello.c -o hello.i
    XXXX@ubuntu:~/hello$ ls
    hello.c  hello.i
    

    説明:1、gcc-E filename.cは1つを表す.cファイルは前処理を行い、Eは大文字2、gcc-E filenameでなければならない.c -o filename.iは、前処理ファイルをfilenameと命名することを示す.i,ここでの-oは小文字3,前処理ファイル用filenameでなければならない.iで表す.
      1 # 1 ""
      2 # 1 ""
      3 # 1 "/usr/include/stdc-predef.h" 1 3 4
      4 # 1 "" 2
      5 # 1 "hello.c"
      6 # 1 "/usr/include/stdio.h" 1 3 4
      7 # 27 "/usr/include/stdio.h" 3 4
      8 # 1 "/usr/include/features.h" 1 3 4
      9 # 367 "/usr/include/features.h" 3 4
     10 # 1 "/usr/include/i386-linux-gnu/sys/cdefs.h" 1 3 4
     11 # 410 "/usr/include/i386-linux-gnu/sys/cdefs.h" 3 4
     12 # 1 "/usr/include/i386-linux-gnu/bits/wordsize.h" 1 3 4
     13 # 411 "/usr/include/i386-linux-gnu/sys/cdefs.h" 2 3 4
     14 # 368 "/usr/include/features.h" 2 3 4
     15 # 391 "/usr/include/features.h" 3 4
     16 # 1 "/usr/include/i386-linux-gnu/gnu/stubs.h" 1 3 4
     17 
     18 
     19 
    
          ……
    855 
    856 
    857 
    858 # 3 "hello.c"
    859 int main(){
    860 
    861   printf("Hello Word
    "); 862 return 0; 863 }

    上記コードセグメントにおいて、行番号1~858が表すコードは=#include==が指す内容であり、行番号859~863のコードは自分で作成したmain関数であり、表示された注釈内容がクリアされていることがわかる.
    コンパイル
    プリプロセッシングプロセスはファイルの1つのプリプロセッシングにすぎず,構文のチェックなどは行われていない.また,このときコードはC言語にすぎず,まずアセンブリ言語に変換する必要があるプロセスをコンパイルと呼ぶ.
    XXXX@ubuntu:~/hello$ gcc -S hello.i -o hello.s
    XXXX@ubuntu:~/hello$ ls
    hello.c  hello.i  hello.s
    

    説明:1、gcc-S filename.iは1対を表す.iファイルをコンパイルするには、Sは大文字2、gcc-S filenameでなければならない.i -o filename.sはコンパイル後のファイルをfilenameと命名することを表す.s,ここの-oは小文字3,コンパイル後のファイルはfilenameでなければならない.sで表します.
    vimコマンドでhelloを開きます.sファイル
      1         .file   "hello.c"
      2         .section        .rodata
      3 .LC0:
      4         .string "Hello Word"
      5         .text
      6         .globl  main
      7         .type   main, @function
      8 main:
      9 .LFB0:
     10         .cfi_startproc
     11         leal    4(%esp), %ecx
     12         .cfi_def_cfa 1, 0
           ……
     31         .cfi_def_cfa 4, 4
     32         ret
     33         .cfi_endproc
     34 .LFE0:
     35         .size   main, .-main
     36         .ident  "GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.10) 5    .4.0 20160609"
     37         .section        .note.GNU-stack,"",@progbits
    

    このときのファイルはすでにAT&Tアセンブリ言語ファイルに翻訳されている.
    アセンブル
    次に、アセンブリ言語から機械言語への翻訳を行い、このプロセスをアセンブリと呼び、プロセスが終了すると、ターゲットファイルを生成する.o.
    XXXX@ubuntu:~/hello$ gcc -c hello.s
    XXXX@ubuntu:~/hello$ ls
    hello.c  hello.i  hello.o  hello.s
    

    説明:1、-cのcは必ず小文字で、-oを加えて命名する必要はありません2、hello.oはターゲットファイルであり、機械言語で作成されているが、まだ実行できず、必要なランタイムファイルが欠けている.
    リンク
    実行可能ファイルを生成するには、実行時ファイルとターゲットファイルをバインドする必要があります.このプロセスはリンクです.次のコマンドを使用します.
    XXXX@ubuntu:~/hello$ gcc hello.o
    XXXX@ubuntu:~/hello$ ls
    a.out  hello.c  hello.i  hello.o  hello.s
    

    このときa.outはファイル生成を実行することができる.
    うんてん
    実行可能ファイルを実行するには、次の手順に従います.
    XXXX@ubuntu:~/hello$ ./a.out 
    Hello Word
    

    このとき、結果Hello Wordが出力されます.