GCC编译器的使用及背后的故事

一、GCC编译器的使用

1、创建一个 hello.c

mkdir test0
cd test0
vim hello.c

hello.c 内容如下:

#include <stdio.h>
int main(void)
{
    
    
	printf("Hello World! \n");
	return 0;
}

2、程序的编译过程

这个程序,一步到位的编译指令是:

gcc hello.c -o test

实质上,上述编译过程是分为四个阶段进行的,即预处理(也称预编译,Preprocessing)、编译(Compilation)、汇编 (Assembly)和连接(Linking)。

预编译(将源文件 hello.c 文件预处理生成 hello.i)

gcc -E hello.c -o hello.i

编译(将预处理生成的 hello.i 文件编译生成汇编程序 hello.s)

gcc -S hello.i -o hello.s

汇编(将编译生成的 hello.s 文件汇编生成目标文件 hello.o)

gcc -c hello.s -o hello.o   # 用gcc进行汇编
as -c hello.s -o hello.o    # 用as进行汇编

链接(分为静态链接和动态链接,生成可执行文件)

gcc hello.c -o hello             # 动态链接
gcc -static hello.c -o hello  # 静态链接

在这里插入图片描述

执行

在这里插入图片描述

用 size 查看文件大小,ldd链接了那些动态库

在这里插入图片描述

3、多个程序文件的编译

通常整个程序是由多个源文件组成的,相应地也就形成了多个编译单元,使用 GCC 能够很好地管理这些编译单元。假设有一个由 test1.c 和 test2.c 两个源文件组成的程序,为了对它们进行编译,并最终生成可执行程序 test,可以使用下面这条命令:

gcc test1.c test2.c -o test

检错
gcc -pedantic illcode.c -o illcode
链接
把所有目标文件链接成可执行文件:

gcc –L /usr/dev/mysql/lib –lmysqlclient test.o –o test

二、GCC编译器背后的故事

1.准备

创建test0,使用vim编写hello.c

mkdir test0
cd test0

编写hello.c

#include <stdio.h>
int main(void) 
{
    
     
printf("Hello World! \n"); 
return 0;
 }

2.编译过程

预处理
使用 gcc 进行预处理

gcc -E hello.c -o hello.i  #-E 使 GCC 在进行完预处理后即停止

编译
使用 gcc 进行编译的命令如下:

gcc -S hello.i -o hello.s  #-S 使 GCC 在执行完编译后停止,生成汇编程序

汇编
使用 gcc 进行汇编的命令如下:

 gcc -c hello.s -o hello.o #-c 使 GCC 在执行完汇编后停止,生成目标文件

链接

gcc hello.c -o hello

在这里插入图片描述

三、分析 ELF 文件

1.ELF 文件的段

readelf -S hello #查看各个段的信息

在这里插入图片描述

2.反汇编 ELF

由于 ELF 文件无法被当做普通文本文件打开,如果希望直接查看一个 ELF 文件包
含的指令和数据,需要使用反汇编的方法。
使用 objdump -D 对其进行反汇编:

objdump -D hello

部分展示:
在这里插入图片描述

四、汇编代码“hello.asm”编译生成可执行程序

在ubuntu中下载安装nasm,对示例汇编代码“hello.asm”编译生成可执行程序,并与上述用C代码的编译生成的可执行程序大小进行对比

1.nasm的安装

在这里插入图片描述

2.创建一个"hello.asm"文件

touch hello.asm
gedit hello.asm

3.编译、链接和运行

nasm -f elf64 hello.asm    //编译
ld -s -o hello hello.o    //链接
./hello                 //输出

在这里插入图片描述

4.汇编与C代码的编译生成的可执行程序大小对比

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43757736/article/details/109122034