编译器背后的故事

编译器背后的故事

学习目标

1.请说明可执行程序是如何被组装的?
(1)阅读、理解和学习材料“用gcc生成静态库和动态库.pdf”和“静态库.a与.so库文件的生成与使用.pdf”,请在Linux系统(Ubuntu)下如实仿做一遍。
(2)在第一次作业的程序代码基础进行改编,除了x2x函数之外,再扩展写一个x2y函数(功能自定),main函数代码将调用x2x和x2y ;将这3个函数分别写成单独的3个 .c文件,并用gcc分别编译为3个.o 目标文件;将x2x、x2y目标文件用 ar工具生成1个 .a 静态库文件, 然后用 gcc将 main函数的目标文件与此静态库文件进行链接,生成最终的可执行程序,记录文件的大小。
(3)将x2x、x2y目标文件用 ar工具生成1个 .so 动态库文件, 然后用 gcc将 main函数的目标文件与此动态库文件进行链接,生成最终的可执行程序,记录文件的大小,并与之前做对比。

2.Gcc不是一个人在战斗。请说明gcc编译工具集中各软件的用途,了解EFF文件格式,汇编语言格式。
(1)阅读、理解和学习材料“Linux GCC常用命令.pdf”和“GCC编译器背后的故事.pdf”,如实仿做一遍。
(2)as汇编编译器针对的是AT&T汇编代码风格,Intel风格的汇编代码则可以用nasm汇编编译器编译生成执行程序。请在ubuntu中下载安装nasm,对示例代码“hello.asm”编译生成可执行程序,并与“hello world”C代码的编译生成的程序大小进行对比。

3.每一个程序背后都站着一堆优秀的代码库。了解实际程序是如何借助第三方库函数完成代码设计。
(1)了解Linux 系统中终端程序最常用的光标库(curses)的主要函数功能,写出几个基本函数名称及功能;
(2)在 win10 系统中,“控制面板”–>“程序”—>“启用或关闭Windows功能”,启用 “telnet client” 和"适用于Linux的Windows子系统"(后面会使用)。 然后打开一个cmd命令行窗口,命令行输入 telnet bbs.newsmth.net,以游客身份体验一下即将绝迹的远古时代的 BBS (一个用键盘光标控制的终端程序)。
(3)在Ubuntu中用 sudo apt-get install libncurses5-dev 安装curses库,请说明 头文件(比如curses.h)和库文件都被安装到哪些目录中;
(4)请参考 “Linux 环境下C语言编译实现贪吃蛇游戏”(http://www.linuxidc.com/Linux/2011-08/41375.htm)或者弹球游戏(https://blog.csdn.net/psc0606/article/details/9990981),用gcc编译生成一个终端游戏,体会curses库如何被链接和使用。

一、可执行文件的组装

1. gcc生成静态库/动态库

进入linux终端,先建立一个作业目录test1,如下图
在这里插入图片描述
然后用vim写如下代码
在这里插入图片描述

由.o文件生成静态库libmyhello.a,如下图
在这里插入图片描述
由.o文件创建动态库libmyhello.so,如下图

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

2. 静态库文件链接(实践)

已建好3个文件main.c,sub1.c,sub2.c,代码如下

//main.c
#include <stdio.h>
#include "sub1.c"
#include "sub2.c"

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

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

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

用gcc编译为.o文件
在这里插入图片描述

将x2x、x2y目标文件用 ar工具生成1个 .a 静态库文件libsub.a
在这里插入图片描述
main函数与此静态库文件进行链接,并运行main文件,正确
在这里插入图片描述

3. 动态库文件链接(实践)

创建动态库文件libsub.so
在这里插入图片描述
将main函数与此动态库文件进行链接,并运行main1文件,正确
在这里插入图片描述
main1文件大小如下,并与main文件比较,两者一样大
在这里插入图片描述

二、gcc编译工具

1. gcc常用命令

创建一个文件夹testgcc,写一个简单程序test,一步到位编译如下
在这里插入图片描述
实质上,上述编译过程是分为四个阶段进行的,即预处理(也称预编译,Preprocessing)、编译 (Compilation)、汇编 (Assembly)和连接(Linking)。

预处理

gcc -E test.c -o test.i

编译为汇编代码(.s文件)

gcc -S test.i -o test.s

汇编为目标文件(.o文件)

gcc -c test.s  -o test.o

连接

gcc test.o -o test

2. nasm初步使用

在ubuntu18.04中安装nasm
在终端输入如下命令:
sudo apt-get install nasm

在testgcc文件夹下创建文件hello.asm代码如下

;hello.asm
section .dara	;
      msg db "Hwllo,world!",0xA	;
      len equ $ - msg	;
section .text	;
global _start	;
_start:		;
	mov edx, len	;
	mov ecx, msg	;
	mov ebx, 1	;
	mov eax, 4	;
	int 0x80	;
	;
	mov ebx, 0	;
	mov eax, 1	;
	int 0x80	;

对hello.asm编译生成可执行程序,并运行
在这里插入图片描述
hello与test文件大小比较,显然nasm编译的文件要小
在这里插入图片描述

在ubuntu中下载安装nasm

安装
  ubuntu11.10下默认没有安装curses函数库,(CentOS下默认已经安装,可以直接在usr/include下查看是否有该头文件来确定)使用
  >sudo apt-get install ncurses-dev 
  安装curses库,这样在curses函数库的头文件和库文件就被分别安装在/usr/include//usr/lib/下,在编译程序时,直接使用命令:
  gcc program.c -o program -lcurses
  完成编译,运行。
 
curses函数库头文件安装位置:/usr/include/
curses函数库库文件安装位置:/usr/lib/

猜你喜欢

转载自blog.csdn.net/lyjccchong/article/details/109136792