其他分享
首页 > 其他分享> > gcc a.c 究竟经历了什么

gcc a.c 究竟经历了什么

作者:互联网

link
你知道一次gcc命令究竟经历了什么吗?

我们先来看一段C语言示例源代码:


// test.cc
#include <stdio.h>

int main() {
   printf("Hello 程序喵\n");
   return 0;
}

 gcc test.cc
 ./a.out
Hello 程序喵

在这里插入图片描述
我们平时都会使用gcc来编译程序,这一行简单的命令其实经历了很多复杂的过程:

首先使用file看一下test.cc文件类型:

 file test.cc
test.c: C source, UTF-8 Unicode text

我们接下来看看这每个过程都做了什么?

预处理

命令:

 gcc -E test.cc -o test.i
或者
cpp test.cc -o test.i
这里可以看出预处理后的文件和预处理前的文件类型是相同的,都是文本文件,也可以直接查看test.i的内容,里面代码较多,就不贴上来了。
其实预处理主要操作有这几个:

编译(生成汇编代码)

命令:

gcc -S test.cc -o test.s

再查看文件类型

 file test.s
test.s: assembler source, ASCII text
        .file   "test.cc"
        .text
        .section        .rodata
.LC0:
        .string "Hello \347\250\213\345\272\217\345\226\265"
        .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                                             

在这里插入图片描述

如图二,编译过程就是把预处理后的文件进行一系列操作生成相应的汇编文件:

汇编

命令:

gcc -c test.s -o test.o
或
as test.s -o test.o
7f45 4c46 0201 0100 0000 0000 0000 0000
0100 3e00 0100 0000 0000 0000 0000 0000
0000 0000 0000 0000 d002 0000 0000 0000
...
...
...
0000 0000 0000 0000 6802 0000 0000 0000
6100 0000 0000 0000 0000 0000 0000 0000
0100 0000 0000 0000 0000 0000 0000 0000

查看文件类型:

file test.o
testt.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped

使用汇编器将汇编代码转成机器可以执行的指令,其实就是将汇编指令和机器指令按照对照表一一翻译。

链接

为什么汇编器不直接生成可执行文件而是生成一个目标文件呢,因为一个文件需要依赖其它好多个库,这些库的符号需要通过链接过程才可以互相配合生成一个可执行文件,需要经历地址和空间分配、符号决议、重定位等步骤,这块内容较多,后续会详细介绍,现在我们可以简单的通过ldd查看一下可执行程序需要依赖的库,这些库都需要在链接过程中被链接才可以使用。
 ldd a.out
	linux-vdso.so.1 (0x00007ffe59c5b000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007efcd6269000)
	/lib64/ld-linux-x86-64.so.2 (0x00007efcd685c000)

标签:gcc,0000,cfi,cc,经历,test,main,究竟
来源: https://blog.csdn.net/luoganttcc/article/details/122301576