编译流程
预编译(preprocess)→编译(compilation)→汇编(assembly)→链接(linking)
实例:
1)相关文件
- main.c - 源代码
- main.s - 汇编代码
- main.o - 二进制文件(执行不可)
- main - 二进制文件(可执行)
2)源代码
#include <stdio.h> int main(){ printf("Hello world!\n"); return 0; }
3)预编译
所谓预编译,指包括宏展开、#include/#ifdef等的引用处理。
可以使用下面的方法查看预编译后的代码。
$ gcc -E main.c
下面是生成的编译后代码的一部分(原文件比较长)
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; typedef signed long int __int64_t; typedef unsigned long int __uint64_t; typedef long int __quad_t; typedef unsigned long int __u_quad_t; ... extern FILE *popen (__const char *__command, __const char *__modes) ; extern int pclose (FILE *__stream); extern char *ctermid (char *__s) __attribute__ ((__nothrow__ , __leaf__)); extern void flockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)); extern int ftrylockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ; extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)); int main(){ printf("Hello world!\n"); return 0; }
由于文件比较长,通过命令gcc -E main.c,会将预编译的结果直接显示在控制终端,无法查看全部内容,
可以通过下面的命令,将结果重定向到新的文件中。
$ gcc -E main.c > preprocess.c
4)编译(侠义)
这里的编译是指将预编译后的源代码转化成汇编代码,可以通过下面的命令输出转化后的汇编代码文件。
$ gcc -S preprocess.c
转化后的汇编代码如下:
.file "preprocess.c" .section .rodata .LC0: .string "Hello World" .text .globl main .type main, @function main: .LFB0: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movl $.LC0, %edi call puts movl $1, %eax popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE0: .size main, .-main .ident "GCC: (Ubuntu/Linaro 4.7.3-12ubuntu1) 4.7.3" .section .note.GNU-stack,"",@progbits