编译器背后的故事

7 篇文章 0 订阅
2 篇文章 0 订阅

学习任务:
1.用gcc生成静态库和动态库.
2.静态库.a与.so库文件的生成与使用
3.学习gcc编译工具集中各软件的用途,了解EFF文件格式,汇编语言格式。
4.请在ubuntu中下载安装nasm,对示例代码“hello.asm”编译生成可执行程序
5.

一.静态库和动态库的运行及使用

1.编写程序
用nano编写两个功能函数和一个主函数

main1.c

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

sub1.c

#include<stdio.h>
float x2x(int a,int b){
  int c;
   c=a+b;
return c;
}

sub2.c

#include<stdio.h>
float x2y(int a, int b)
{
 return a-b;
}

2.生成.o文件
gcc编译为3个.o 目标文件
在这里插入图片描述

3.静态库文件的生成及链接执行
(1)由.o文件创建静态库

静态库文件名的命名规范是以 lib 为前缀,紧接着跟静态库名,扩展名为.a。例如:我们将 创建的静态库名为 sub,则静态库文件名就是 libsub.a。在创建和使用静态库时, 需要注意这点。创建静态库用 ar 命令。在系统提示符下键入以下命令将创建静态库文件 libsub.a。

输入如下指令,并输入ls指令查看结果如图

ar -crv libsub.a  sub1.o sub2.o

在这里插入图片描述
(2)在程序中使用静态库
在程序中生成静态库有以下三种方法:

方法一: gcc -o hello main.c -L. –lmyhello 自定义的库时,main.c 还可放在-L.和 –lmyhello 之间,但是不能放在它俩之后,否则会提 示 myhello 没定义,但是是系统的库时,如 g++ -o main(-L/usr/lib) -lpthread main.cpp 就不出错。
方法二: #gcc main.c libsub.a -o hello
方法三: 先生成 main.o: gcc -c main.c 再生成可执行文件: gcc -o hello main.o libsub.a
动态库连接时也可以这样做。

在这里插入图片描述
在用主程序使用所生成的静态库(hello)
在这里插入图片描述

4.动态库文件的生成及链接执行
(1)由.o 文件创建动态库文件

动态库文件名命名规范和静态库文件名命名规范类似,也是在动态库名增加前缀 lib,但其 文件扩展名为.so。例如:我们将创建的动态库名为 myhello,则动态库文件名就是 libmyhello.so。

输入以下命令,并使用ls命令查看目录如图

gcc -shared -fPIC -o libmyhello.so sub1.o sub2.o (-o 不可少)

在这里插入图片描述

(2)在程序中使用动态库
先运行 gcc 命令生成目标文件,再运行它看看结果。

gcc -o hello main.c -L. -lmyhello

会显示如下内容:./hello: error while loading shared libraries: libmyhello.so: cannot open shar ed object file: No such file or directory

解决方法:将文件 libmyhello.so 移动到目录/usr/lib 中
在这里插入图片描述

二.GCC的运行

  1. gcc的编译过程

步骤: 预处理->编译->汇编->链接

示例:

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

(1)预编译

将源文件 hello.c 文件预处理生成 hello.i

在这里插入图片描述

(2)编译

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

在这里插入图片描述

(3)汇编

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

在这里插入图片描述

(4)链接

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

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

2.EFF文件格式,汇编语言格式
(1) ELF 文件的段

ELF 文件格式如下图所示,位于 ELF Header 和 Section Header Table 之间的都是段(Section)

一个典型的 ELF 文件包含下面几个段:

text:已编译程序的指令代码段。 .

rodata:ro 代表 read only,即只读数据(譬如常数 const)。

data:已初始化的 C 程序全局变量和静态局部变量。

bss:未初始化的 C 程序全局变量和静态局部变量。 .

debug:调试符号表,调试器用此段的信息帮助调试。
在这里插入图片描述
(2)反汇编 ELF
由于 ELF 文件无法被当做普通文本文件打开,如果希望直接查看一个 ELF 文件包 含的指令和数据,需要使用反汇编的方法。

使用 objdump -D 对其进行反汇编

三.nasm的安装使用

1.安装
(1)方法一:

ubuntu中安装方法

(2)方法二:

博主使用的本方法

sudo apt install nasm

在这里插入图片描述
然后输入以下指令检查是否安装完成:
在这里插入图片描述
2.使用nasm对示例代码“hello.asm”编译生成可执行程序
创建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         ; 调用内核功能

  1. 编译输出
  2. 在这里插入图片描述

四.Linux中的第三方库函数

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

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

  1. 安装curses库

在Ubuntu中用 sudo apt-get install libncurses5-dev

可以查看头文件所在目录在这里插入图片描述
3.以游客身份体验一下即将绝迹的远古时代的 BBS (一个用键盘光标控制的终端程序)

在 win10 系统中,“控制面板”–>“程序”—>“启用或关闭Windows功能”,启用 “telnet client” 和"适用于Linux的Windows子系统"(后面会使用)。

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

然后打开一个cmd命令行窗口,命令行输入 telnet bbs.newsmth.net

在这里插入图片描述
4…Linux 环境下C语言编译实现一些游戏

访问以下链接即可学习编写

Linux下编写贪吃蛇游戏
弹球游戏
示例贪吃蛇游戏:
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值