SPO 666週5反射

4689 ワード

こんにちは皆さん、SPO 600(ソフトウェア可搬性と最適化)反射と余分の探査ブログの週6にようこそ!我々は5週間のアセンブリ言語を学んでいる.今週、私たちはCプログラムがどのように構築され、コンパイルされ、最適化されるかについて話します.
Cプログラマの初心者として、ソースコードがバイナリ実行ファイルになる方法に興味がありますか?今日から始めます.

// hello.c
#include <stdio.h>
int main(){
    printf("hello world!\n");
}
我々は、すべてのプログラマのための最初のプログラムです簡単なHelloWorldプログラムから起動します.
このソースコードをコンパイルしたいなら、Linuxシステムに必要なのは以下の通りです.
$ gcc hello.c # compile
$ ./a.out # execute
hello world!
私たちがコードを実行するのは非常に一般的です、しかし、我々が上記で見るものと同じくらい単純なこのプロセスですか?答えは何ですかgcc 上記のコンパイル期間中は実際に行います.

The gcc コンパイラは5つのステップを実行します.プリプロセッサ、コンパイル、最適化、アセンブリ、リンク.
具体的には別の例を挙げたいと思います.
// mymath.h
#ifndef MYMATH_H
#define MYMATH_H
int add(int a, int b)
int sum(int a, int b);
#endif

// mymath.c
int add(int a, int b){
    return a+b;
}
int sub(int a, int b){
    return a-b;
}

// test.c
#include <stdio.h>
int main(){
    int a = 2;
    int b = 3;
    int sum = add(a, b); 
    printf("a=%d, b=%d, a+b=%d\n", a, b, sum);
}
このプログラムでは、我々は単に2つの整数の合計を見つけるために作成しました.

前処理
前処理はヘッダーファイルの宣言をその内容に置き換えます.処理の後、あなたはより大きなファイルを得ます.テストを前処理するには、以下のコマンドを使用できます.c
gcc -E -I./inc test.c -o test.i
または
$ cpp test.c -I./inc -o test.i
- eコマンドで前処理が終了したら終了する.
- Iヘッダファイルのフォルダを決定する.
- Oは出力ファイルの名前を決定することです.
とテストのサイズ.私はテストのために17691 Bです.Cは146 Bである.

編集
この部分のコンパイルは、プリコードされたコードをアセンブリコードに組み立てることです.次のコードを使用できます.
$ gcc -S -I./inc test.c -o test.s
テストの内容.sは以下です
   .file   "test.c"
    .section    .rodata
.LC0:
    .string "a=%d, b=%d, a+b=%d\n"
    .text
    .globl  main
    .type   main, @function
main:
.LFB0:
    .cfi_startproc
    pushl   %ebp
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp
    .cfi_def_cfa_register 5
    andl    $-16, %esp
    subl    $32, %esp
    movl    $2, 20(%esp)
    movl    $3, 24(%esp)
    movl    24(%esp), %eax
    movl    %eax, 4(%esp)
    movl    20(%esp), %eax
    movl    %eax, (%esp)
    call    add 
    movl    %eax, 28(%esp)
    movl    28(%esp), %eax
    movl    %eax, 12(%esp)
    movl    24(%esp), %eax
    movl    %eax, 8(%esp)
    movl    20(%esp), %eax
    movl    %eax, 4(%esp)
    movl    $.LC0, (%esp)
    call    printf
    leave
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret 
    .cfi_endproc
.LFE0:
    .size   main, .-main
    .ident  "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2"
    .section    .note.GNU-stack,"",@progbits
私が知っている限りではassembly code 本当にここに.私がそれを理解するならば、私はこれのためにもう一つのポストをつくります.

アセンブルする
アセンブルはアセンブリコードをmachine code . この手順では、バイナリ形式のオブジェクトファイルを作成します.使えます
gcc -c test.s -o test.o
すべてのソースファイルのオブジェクトファイルを作成します.

リンク
リンクプロセスは、プログラムが最終的に作成する必要があるすべてのライブラリファイルを接続しますexecutable file(.exe) .

結論と私の想い
上記の手順によると、私たちは、プロセスが前に考えたものではないことがわかりました.コンパイルは私たちがアクセスするための実行可能ファイルを作成するために5つの手順を経て、ソースコードファイルを正常にコンパイルするには、上記のパイプラインから任意の1つのステップをスキップすることはできません.
しかし、まだ使用することができますので、あまり心配しないでください.
$ gcc hello.c # compile
$ ./a.out # execute