赞
踩
我们将在Linux操作系统中,以C语言的Hello World程序为例,用gcc编译器分步执行这四个步骤。
我们有再熟悉不过的HelloWorld程序,hello.c
:
#include <stdio.h>
int main(){
printf("Hellow World.\n");
return 0;
}
预处理阶段 预处理器(cpp)根据以
#
字节开头的命令,修改原始的C程序,
执行预处理命令:gcc -E hello.c -o hello.i
,我们得到由.c
文件得到.i
文件:hello.i
:
# 1 "hello.c" # 1 "<built-in>" # 1 "<command-line>" # 31 "<command-line>" # 1 "/usr/include/stdc-predef.h" 1 3 4 # 32 "<command-line>" 2 # 1 "hello.c" # 1 "/usr/include/stdio.h" 1 3 4 # 27 "/usr/include/stdio.h" 3 4 # 1 "/usr/include/x86_64-linux-gnu/bits/libc-header-start.h" 1 3 4 # 33 "/usr/include/x86_64-linux-gnu/bits/libc-header-start.h" 3 4 # 1 "/usr/include/features.h" 1 3 4 # 424 "/usr/include/features.h" 3 4 # 1 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 1 3 4 # 427 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 3 4 # 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4 # 428 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 2 3 4 # 1 "/usr/include/x86_64-linux-gnu/bits/long-double.h" 1 3 4 # 429 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 2 3 4 # 425 "/usr/include/features.h" 2 3 4 # 448 "/usr/include/features.h" 3 4 # 1 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 1 3 4 # 10 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 3 4 # 1 "/usr/include/x86_64-linux-gnu/gnu/stubs-64.h" 1 3 4 # 11 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 2 3 4 # 449 "/usr/include/features.h" 2 3 4 # 34 "/usr/include/x86_64-linux-gnu/bits/libc-header-start.h" 2 3 4 # 28 "/usr/include/stdio.h" 2 3 4
编译阶段 编译器(cc1)将文本文件
hello.i
翻译成文本文件hello.s
,它包含一个汇编语言程序。
执行编译命令:gcc -S hello.i -o hello.s
,我们得到由.i
文件得到.s
文件:hello.s
,这就是汇编文件:
.file "hello.c" .text .section .rodata .LC0: .string "Hellow 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 leaq .LC0(%rip), %rdi call puts@PLT movl $0, %eax popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE0: .size main, .-main .ident "GCC: (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0" .section .note.GNU-stack,"",@progbits
汇编阶段 汇编器(as)将
hello.s
翻译成机器语言指令,把这些指令打包成一种叫做可重定位目标程序的格式,并保存在hello.o
文件中,这是一个二进制文件,无法直接用文本编辑器查看。
执行编译命令:gcc -c hello.s -o hello.o
,我们得到由.s
文件得到.o
文件:hello.o
,可重定向文件文件,这个文件就不是文本文件了,因此无法展示。
至此以上三步其实可以由-c
参数直接得到可重定向文件:gcc -c hello.c -o hello.o
,以上是为了说明预处理和编译两步,专门分步进行,以查看输出。
链接阶段
hello
程序调用了printf
函数,它来自C标准库,具体存在于一个已经预编译好的printf.o
文件,链接器(ld)负责将这个文件与我们的hello文件合并起来。
执行链接命令gcc hello.o -o hello
,我们有.s
文件得到可执行文件hello
,直接./hello
执行即可在命令行打印输出Hellow World
。
Ref:CSAPP
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。