GCC背景强大? 探寻linux系统下GCC编译器的背后故事!

一.在vim和gcc编译环境下生成.a静态库和.so动态库

gcc编译器不是一个人在战斗,gcc其实背后有一堆战友我们来看看有哪些
首先创建一个基础的helloword文件
在这里插入图片描述
输入gcc -E hello.c -o hello.i:生成hello.i文件
gcc -S hello.i -o hello.s:将生成的hello.i文件编译生成汇编hello.s在这里插入图片描述
如下图
在这里插入图片描述

汇编部分


gcc -c hello.s -o hello.o:生成hello.o文件
as -c hello.s-o hello.o 生成汇编目标文件
在这里插入图片描述

关于链接


我们这里使用动态库进行链接,生成的ELF可执行文件大小和链接的动态库,如下:
gcc hello.c -o hello
size hello :查看size的大小:
在这里插入图片描述
ldd hello 可以看出可执行文件连接了很多其他动态库,主要是linux和glibc的动态库
在这里插入图片描述
也可以使用其他命令查看:
gcc -static hello.c -o hello:会使静态库进行链接,生成ELF文件
gcc - static hello.c -o hello
size hello:查看大小
在这里插入图片描述
ldd hello
在这里插入图片描述
说明不是链接的动态库!

分析ELF文件

代码:readelf -S hello:查看hello

在这里插入图片描述
在这里插入图片描述

反汇编ELF

使用 objdump-Dhello对其进行反汇编
出现一千多行:
在这里插入图片描述
再使用gcc -o hello -g hello.c
objdump -S hello 将其c语言代码混合显示出来
仍然出现一千多行
在这里插入图片描述

接下来我们用

二.gcc生成静态库和动态库

创建作业目录,然后保存在这里插入图片描述
分别生成3个程序:hello.c hello.h main.c
在这里插入图片描述
代码如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

用如下命令将.c文件编译成.o文件
gcc -c hello.c
结果如下
在这里插入图片描述
然后输入代码ls
在这里插入图片描述
接下来就开始创建静态库
命令如下:
ar-crv libmy hello.a hello.o
然后看看是否生成静态库,再次输入ls
结果如下:
在这里插入图片描述
成功!

调用静态库

命令代码如下:gcc main.c libmyhello.a -o hello
在将结果编译出来:./hello
得到一个串英文就是刚开始输入
good word
删除hello静态库文件看是否链接成功
在这里插入图片描述
正常运行,说明已经成功。

最后创建一个动态库
命令:gcc main.c libmyhello.so -o hello
结果和上面一样,成功。

动态库与静态库的比较

创建一个新的文件夹,并且生成几个函数,分别是sub1.h,sub1.c,sub2.h,sub2.c main.c
在这里插入图片描述

下面分别是每个函数的代码:
main.c

#include<stdio.h>
#include"sub1.h"
#include"sub2.h"
int main(){
	int a = 2, b = 3;
	printf("%d + %d = %f\n", a, b, x2x(a, b));
	printf("%d × %d = %f\n", a, b, x2y(a, b));
	return 0;
}

sub1.h

#ifndef SUB1_H
#define SUB1_H 
float x2x(int a, int b);
#endif //SUB1_H

sub1.c

#include"sub1.h"

float x2x(int a, int b)
{

return a + b;	
}

sub2.c

#include"sub2.h"

float x2y(int a, int b){
return a-b;	
}

sub2.h:

#ifndef SUB2_H
#define SUB2_H 
float x2y(int a, int b);
#endif //SUB2_H

静态库的使用

创建一个.o文件
代码:gcc -c sub1.c sub2.c
在这里插入图片描述
然后用此文件常见静态库(静态库的创建可以参考上面的操作)

ar -crv libsub1.a sub1.o
ar -crv libsub2.a sub2.o

在用ls指令查看(可以发现我们这里已经可以熟悉使用这些指令了)

在这里插入图片描述
再用这个静态库创建一个可执行文件

gcc -static main.c libsub1.a libsub2.a -o main1 

再查看
在这里插入图片描述
接下来我们

创建动态库

gcc -shared -fPIC -o libsub1.so sub1.o
gcc -shared -fPIC -o libsub2.so sub2.o

调用动态库别并将动态库移动

gcc main.c libsub1.so libsub2.so -o main2
sudo mv libsub1.so /usr/lib
sudo mv libsub2.so /usr/lib
./main2

在这里插入图片描述

纠错

我们发现出现了一个常识性错误,来尝试找一下哪个地方是错误的

在这里插入图片描述
我们根据提示,我们为无法获取这个so的stat,我们在静态库生成一个so文件,再次将每一步都重新来过,
就可以得到正确的结果!
在这里插入图片描述

链接动态库

这里给大家分享一个清理屏幕的代码

clear

这样屏幕就变得干净啦!
在这里插入图片描述

接下来进入正题

先用.o文件创建动态库

gcc -shared -fPIC -o libsub1.so sub1.o
gcc -shared -fPIC -o libsub2.so sub2.o

在用ls代码查看

在这里插入图片描述
调用动态库

gcc main.c libsub1.so libsub2.so -o main2
sudo mv libsub1.so /usr/lib
sudo mv libsub2.so /usr/lib
./main2

在这里插入图片描述
正确调用!

三.比较两个可执行文件的大小

按上述方法由静态库链接生成的可执行文件,不是完全由静态库链接生成的,因为在 main.c 中调用的 stdio.h
是由动态链接的,所以需要重新由静态库链接生成一个可执行文件,否则可能将会出现静态库生成的可执行文件小于动态库生成的

gcc -static main.c libsub1.a libsub2.a -o main1 
size main1
ldd main1
size main2
ldd main2

在这里插入图片描述
size和ldd请参考上面我给出的解释
上面一部分是静态的
在这里插入图片描述后面则是动态的
在这里插入图片描述

探索GCC是如何编译的

其中一部分在刚开始的第一节我已经解释了,接下来我们安装一个软件
nasm编译器,在这个编译器里完成对hello word的编译和与gcc的比较
输入代码

sudo apt install nasm

在输入自己的密码就行了
在这里插入图片描述我们检查一下是否安装成功

在这里插入图片描述虚拟机自动下载为2.14.02版本
然后编译汇编 hello.asm文件,并于C代码的编译生成的程序大小进行对比

hello.asm 内容如下:

; hello.asm section .data ; 数据段声明
msg db “Hello, world!”, 0xA ; 要输出的字符串
len equ $ - msg ; 字串长度
section .text ; 代码段声明 global _start ; 指定入口函数
_start: ; 在屏幕上显示一个字符串
mov edx, len ; 参数三:字符串长度
mov ecx, msg ; 参数二:要显示的字符串
mov ebx, 1 ; 参数一:文件描述符(stdout)
mov eax, 4 ; 系统调用号(sys_write)
int 0x80 ; 调用内核功能
; 退出程序
mov ebx, 0 ; 参数一:退出代码
mov eax, 1 ; 系统调用号(sys_exit)
int 0x80 ; 调用内核功能

开始编译:

在这里插入图片描述
在这里插入图片描述

nasm -f elf64 hello.asm

这里我们出现了一个错误
在这里插入图片描述
没找到那个文件,我排查之后发现,我成立文件的时候因为对nasm编译器不熟悉,因此就对语法不熟悉,少加了一个点,应该是 vim hello.asm,修改之后就可以了
在这里插入图片描述
在链接

nasm -f elf64 hello.asm

在这里插入图片描述

在这里插入图片描述
我们发现了只有只有汇编生成的大小,c没有生成,这是因为我在完成text1时,虚拟机出现了黑屏现象,解决之后,text1的所有hello.c文件已经丢失,我们可以看到第一部分的hello的大小
在这里插入图片描述
对比之后发现汇编生成的大小比c生成的要小得多!
怎么解决黑屏现象? 在我的博客里可以找到解决方法哦!

四.体验在linux操作系统下玩游戏

用游客身份体验即将绝迹的远古时代的BBC

在 win10 系统中,“控制面板”–>“程序”—>“启用或关闭Windows功能”,启用 “telnet client” 和 “适用于Linux的Windows子系统”(后面会使用),然后重启。
在这里插入图片描述
在这里插入图片描述

打开amd命令行窗口

 telnet bbs.newsmth.net

在这里插入图片描述
接下来就可以体验啦!
在这里插入图片描述

贪吃蛇游戏

链接: 贪吃蛇游戏

先安装curses

了解Linux 系统中终端程序最常用的光标库(curses)

initscr(): initscr() 是一般 curses
程式必须先呼叫的函数, 一但这个函数被呼叫之后, 系统将根据终端机的形态并启动 curses 模式endwin(): curses
通常以呼叫 endwin() 来结束程式. endwin() 可用来关闭curses 模式, 或是暂时的跳离 curses
模式refresh(): refresh() 为 curses 最常呼叫的一个函式move(y,x): 将游标移动至 x,y
的位置echochar(ch)/addch(ch): 显示某个字元

sudo apt-get install libncurses5-dev

在这里插入图片描述
安装完毕

编译

mkdir testSnake
cd testSnake
vim mysnake.c
gcc mysnake.c -lcurses -o mysnake 
./mysnake

在这里插入图片描述
在这里插入图片描述注意玩游戏的时候吃了一个球就不能按反方向了哟,因为那会把自己的尾巴吃到,就会像我这样死掉!

五.总结

此篇是关于GCC编译器的运用,熟悉一下GCC背后一同作战的队友!还有动态库和静态库使用和比较,nasm编译器和GCC的比较,最后体验一下在linux系统下玩游戏的感觉!过程中出现了很多的错误,检查出来解决的感觉十分良好!

六.参考链接

链接: 贪吃蛇.
链接: 关于curses.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值