Linux C程序的预处理、编译、汇编、链接及运行过程

Linux C程序的预处理、编译、汇编、链接及运行过程

  • Hello Word 程序直接编译运行过程
  • 预处理
  • 编译
  • 汇编
  • 链接
  • 运行

Hello Word 程序直接编译运行过程

在Linux系统下,任意目录内创建一个简单的C程序,命名为hello.c,其代码如下:

  1 #include 
  2 int main(){
  3   //这里有个注释
  4   printf("Hello Word\n");
  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

以上是一个程序最简单、最快捷的编译运行方式,但是在实际上,程序从代码到机器可执行的过程中,涉及预处理、编译、汇编、链接及运行等过程,了解这些过程是十分有必要的。

预处理

对上面的程序hello.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 表示对一个.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\n");
862   return 0;
863 }

上述代码段中,行号1~858所代表的代码即是 ==#include ==所指向的内容,行号859~863的代码即是自己编写的main函数,可以看到,所标示的注释内容被清空了。

编译

预处理过程只是对文件的一个预处理,并没有进行语法的检查等。而且此时代码还只是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 表示对一个.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。

你可能感兴趣的:(Linux,C)