结合“hello world”探讨gcc编译程序的过程


1. gcc简介

 

gcc/g++GNU工程的CC++编译器。都要用四个步骤中的一个或多个处理输入文件。

·         预处理(preprocessing)

·         编译(compilation)

·         汇编(assembly)

·         连接(linking)

 

源文件后缀名标识源文件的语言,但是对编译器来说,后缀名控制着缺省设定。

gcc命令的一般格式为:gcc [选项] 要编译的文件 [选项] [目标文件]

 

gcc的详细内容,可参考gcc manual

 

2. gcc的输出选项

 

gcc输出选项,-o后指定输出文件名,gcc解释如下。

`-o FILE'

     Place output in file FILE.  This applies regardless to whatever sort of output is being produced, whether it be an executable file, an object file, an assembler file or preprocessed C code.

     If `-o' is not specified, the default is to put an executable file in `a.out', the object file for `SOURCE.SUFFIX' in `SOURCE.o', its assembler file in `SOURCE.s', a precompiled header file in `SOURCE.SUFFIX.gch', and all preprocessed C source on standard output.

 

    指定输出文件为FILE,该选项不考虑GCC产生什么输出,无论是可执行文件、目标文件、汇编文件还是预处理后的C代码。

    如果没有使用`-o'选项,默认的输出结果是:可执行文件为a.outsource.suffix的目标文件是source.o,汇编文件是source.s,而预处理后的C代码送往标准输出。

 

3. "hello wolrd"的处理过程

 

本文以"hello world"程序,探讨GCC编译程序的过程。

 

hello.c文件内容如下。

#include <stdio.h>

 

int main(int argc, char **argv)

{

    printf("Hello World! via %x\n", printf);

    return 0;

}

 

3.1 预处理(preprocessing)

 

在该阶段,编译器将C源代码中的包含的头文件如stdio.h编译进来,可以使用gcc的选项”-E”进行查看预处理结果。

 

Gcc manual中对-E选项的解释如下。

`-E'

     Stop after the preprocessing stage; do not run the compiler proper. The output is in the form of preprocessed source code, which is sent to the standard output.

     Input files which don't require preprocessing are ignored.

    预处理后停止,不进行编译。预处理后的代码送往标准输出。GCC忽略任何不需要预处理的输入文件。

 

格式:gcc -E hello.c -o hello.i

作用:对hello.c进行预处理输出为hello.i文件

 

Hello.c被预处理后的hello.i文件。

# 1 "hello.c"

# 1 "<built-in>"

# 1 "<command line>"

# 1 "hello.c"

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

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

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

# 335 "/usr/include/features.h" 3 4

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

# 360 "/usr/include/sys/cdefs.h" 3 4

# 1 "/usr/include/bits/wordsize.h" 1 3 4

# 361 "/usr/include/sys/cdefs.h" 2 3 4

# 336 "/usr/include/features.h" 2 3 4

# 359 "/usr/include/features.h" 3 4

# 1 "/usr/include/gnu/stubs.h" 1 3 4

 

 

# 1 "/usr/include/bits/wordsize.h" 1 3 4

# 5 "/usr/include/gnu/stubs.h" 2 3 4

 

 

# 1 "/usr/include/gnu/stubs-32.h" 1 3 4

# 8 "/usr/include/gnu/stubs.h" 2 3 4

# 360 "/usr/include/features.h" 2 3 4

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

 

 

# 1 "/usr/lib/gcc/i386-RedHat-linux/4.1.2/include/stddef.h" 1 3 4

# 214 "/usr/lib/gcc/i386-redhat-linux/4.1.2/include/stddef.h" 3 4

typedef unsigned int size_t;

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

 

# 1 "/usr/include/bits/types.h" 1 3 4

# 28 "/usr/include/bits/types.h" 3 4

# 1 "/usr/include/bits/wordsize.h" 1 3 4

# 29 "/usr/include/bits/types.h" 2 3 4

 

 

typedef unsigned char __u_char;

typedef unsigned short int __u_short;

typedef unsigned int __u_int;

typedef unsigned long int __u_long;

 

 

typedef signed char __int8_t;

typedef unsigned char __uint8_t;

typedef signed short int __int16_t;

typedef unsigned short int __uint16_t;

typedef signed int __int32_t;

typedef unsigned int __uint32_t;

 

 

__extension__ typedef signed long long int __int64_t;

__extension__ typedef unsigned long long int __uint64_t;

 

 

__extension__ typedef long long int __quad_t;

__extension__ typedef unsigned long long int __u_quad_t;

# 131 "/usr/include/bits/types.h" 3 4

# 1 "/usr/include/bits/typesizes.h" 1 3 4

# 132 "/usr/include/bits/types.h" 2 3 4

 

...

 

3.2 编译(compilation)

 

在这个阶段中,Gcc首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,Gcc把代码翻译成汇编语言。可以使用”-S”选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码。

 

Gcc manual中对-S选项的解释如下。

`-S'

     Stop after the stage of compilation proper; do not assemble.  The output is in the form of an assembler code file for each non-assembler input file specified.

     By default, the assembler file name for a source file is made by replacing the suffix `.c', `.i', etc., with `.s'. Input files that don't require compilation are ignored.

     编译后即停止,不进行汇编。对于每个输入的非汇编语言文件,输出文件是汇编语言文件。

     缺省情况下,GCC通过用`.o'替换源文件名后缀`.c',`.i'等以产生目标文件名。可以使用-o选项指定选择其他名字。GCC忽略任何不需要编译的输入文件。

 

格式:gcc –S hello.i –o hello.s

作用:将预处理输出文件hello.i汇编成hello.s文件

 

Hello.i被汇编后的hello.s文件。

  .file        "hello.c"

  .section        .rodata

.LC0:

  .string        "Hello World! via %x\n"

  .text

.globl main

  .type        main, @function

main:

  leal        4(%esp), %ecx

  andl        $-16, %esp

  pushl        -4(%ecx)

  pushl        %ebp

  movl        %esp, %ebp

  pushl        %ecx

  subl        $20, %esp

  movl        $printf, 4(%esp)

  movl        $.LC0, (%esp)

  call        printf

  movl        $0, %eax

  addl        $20, %esp

  popl        %ecx

  popl        %ebp

  leal        -4(%ecx), %esp

  ret

  .size        main, .-main

  .ident        "GCC: (GNU) 4.1.2 20070925 (Red Hat 4.1.2-33)"

  .section        .note.GNU-stack,"",@progbits

  • 1
  • 2
  • 下一页

相关内容