C - 从源码到可运行程序
环境
操作系统: Win10 编译系统: mingw-w64
前言
了解程序从源代码开始, 到生成可运行程序是怎么一个流程.
生命周期
C 程序主要经过这个几个流程:
- 预处理器
- 编译器
- 汇编器
- 链接器
最后生成可执行文件.
预处理器
让我们来编写一个 C 程序 hello.c
#include <stdio.h> int main() { printf("hello, world "); return 0; }
执行命令 gcc -E hello.c -o hello.i 将会得到预处理好的文件 hello.i, hello.i 包含了所引入的头文件 <stdio.h> 相关信息:
编译器
紧接着, 该编译器出场了, 执行命令 gcc -S hello.i -o hello.s
.file "hello.c" .text .def __main; .scl 2; .type 32; .endef .section .rdata,"dr" .LC0: .ascii "hello, world " .text .globl main .def main; .scl 2; .type 32; .endef .seh_proc main main: pushq %rbp .seh_pushreg %rbp movq %rsp, %rbp .seh_setframe %rbp, 0 subq $32, %rsp .seh_stackalloc 32 .seh_endprologue call __main leaq .LC0(%rip), %rcx call puts movl $0, %eax addq $32, %rsp popq %rbp ret .seh_endproc .ident "GCC: (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 8.1.0" .def puts; .scl 2; .type 32; .endef
生成的文件保存着 hello.c 对应的汇编代码.
汇编器
有了汇编代码, 那么就需要汇编器帮我们生成和机器相关的可重定位目标文件. 执行命令 gcc -c hello.s -o hello.o 则就会生成二进制文件 hello.o, 最后一步则就是链接器了.
链接器
链接器(Linker)是一个程序, 将一个或多个由编译器和汇编器生成的目标文件外加库链接为一个可执行文件. 目标文件包括机器码和链接器可用信息的程序模块. 简单的讲, 链接器的工作就是解析未定义的符号引用, 将目标文件的占位符替换为符号的地址. 链接器还要完成程序中各目标文件的地址空间组织, 这可能涉及重定位工作. —百度百科
例如我们的 hello.c 文件, 经过汇编器处理后会得到 hello.o 目标文件, 但我们还调用了一个系统函数 printf(), 所以还需要相对应的目标文件, 和我们自己编写的 hello.o 目标文件组合生成可执行目标程序, 链接器会自动帮我们寻找这些系统目标文件. 执行命令 gcc hello.o -o hello.exe
最后执行 hello.exe 就会打印出
总结
这里我们只是简单的了解程序是如何生成的, 以及相关的参数. gcc -E 预处理器 gcc -S 编译器 gcc -c 汇编器 gcc 链接器
上一篇:
IDEA上Java项目控制台中文乱码