文章目录
- 一. 学习并掌握可执行程序的编译、组装过程。
- 1.用gcc生成静态库和动态库
- 2.静态库.a与.so库文件的生成与使用
- (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函数的目标文件与此动态库文件进行链接,生成最终的可执行程序,记录文件的大小,并与之前做对比。
- 二. Gcc不是一个人在战斗。请说明gcc编译工具集中各软件的用途,了解EFF文件格式。
- 1.GCC编译器背后的故事
- 2.Linux GCC常用命令
- 三. 编写一个C程序,重温全局常量、全局变量、局部变量、静态变量、堆、栈等概念,在Ubuntu(x86)系统和STM32(Keil)中分别进行编程、验证(STM32 通过串口printf 信息到上位机串口助手) 。
- 1、全局变量
- 2、局部变量
- 3.栈区
- 4.堆区
- 5.堆和栈的区别
- 四.总结
一. 学习并掌握可执行程序的编译、组装过程。
(1)阅读、理解和学习材料“用gcc生成静态库和动态库.pdf”和“静态库.a与.so库文件的生成与使用.pdf”,请在Linux系统(Ubuntu)下如实仿做一遍。
1.用gcc生成静态库和动态库
1.1 编译生成例子程序hello.h、hello.c、main.c
1.2 将hello.c编译成.o的文件
1.3 由.o文件创建静态库
1.4 在程序中使用静态库
1.5 由.o文件创建动态库文件
1.6 在程序中使用动态库
2.静态库.a与.so库文件的生成与使用
2.1新建一个文件夹test2,在里面编译生成所需要的四个文件A1.c、A2.c、A.h、test.c。
2.2 静态库.a的生成与使用
使用.a库文件创建可执行程序
2.3 共享.so文件的生成与使用
(2)在第一次作业的程序代码基础进行改编,除了x2x函数之外,再扩展写一个x2y函数(功能自定),main函数代码将调用x2x和x2y ;将这3个函数分别写成单独的3个 .c文件,并用gcc分别编译为3个.o 目标文件;将x2x、x2y目标文件用 ar工具生成1个 .a 静态库文件, 然后用 gcc将 main函数的目标文件与此静态库文件进行链接,生成最终的可执行程序,记录文件的大小。
1.编写x2x、x2y、main函数
2.使gcc编译sub1.c和sub2.c得到.o文件
3.使用ar命令生成静态库
4.在程序中使用静态库
(3)将x2x、x2y目标文件用 ar工具生成1个 .so 动态库文件, 然后用 gcc将 main函数的目标文件与此动态库文件进行链接,生成最终的可执行程序,记录文件的大小,并与之前做对比。
1.使用gcc命令生成动态库
2.在程序中使用动态
二. Gcc不是一个人在战斗。请说明gcc编译工具集中各软件的用途,了解EFF文件格式。
学习任务如下:阅读、理解和学习材料“Linux GCC常用命令.pdf”和“GCC编译器背后的故事.pdf”,如实仿做一遍。
1.GCC编译器背后的故事
1.先创建一 个工作目录 test0,然后用文本编辑器生成一个 C 语言编写的简单 Hello.c 程序为示例
2.编译过程
2.1预处理
2.2编译
2.3汇编
2.4链接
3.分析ELF文件
3.1 ELF文件的段
3.2.反汇编ELF
2.Linux GCC常用命令
1.简单编译一个test.c文件
2.预处理
3.编译为汇编代码
4.汇编
5.连接
三. 编写一个C程序,重温全局常量、全局变量、局部变量、静态变量、堆、栈等概念,在Ubuntu(x86)系统和STM32(Keil)中分别进行编程、验证(STM32 通过串口printf 信息到上位机串口助手) 。
(1)归纳出Ubuntu、stm32下的C程序中堆、栈、全局、局部等变量的分配地址,进行对比分析;
1、全局变量
在所有函数外部定义的变量称为全局变量(Global Variable),它的作用域默认是整个程序,也就是所有的源文件,包括 .c 和 .h 文件。
a、b、x、y 都是在函数外部定义的全局变量。C语言代码是从前往后依次执行的,由于 x、y 定义在函数 func1() 之后,所以在 func1() 内无效;而 a、b 定义在源程序的开头,所以在 func1()、func2() 和 main() 内都有效。
2、局部变量
定义在函数内部的变量称为局部变量(Local Variable),它的作用域仅限于函数内部, 离开该函数后就是无效的,再使用就会报错。例如:
3.栈区
由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
4.堆区
一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收 。它与数据结构中的堆不同,分配方式类似于链表。
5.堆和栈的区别
stack的空间由操作系统自动分配/释放,heap上的空间手动分配/释放。
stack的空间有限,heap是很大的自由存储区。
程序在编译期和函数分配内存都是在栈上进行,且程序运行中函数调用时参数的传递也是在栈上进行。
(2)加深对ARM Cortex-M/stm32F10x的存储器地址映射的理解。下图是一个Cortex-M4的存储器地址映射示意图(与Cortex-M3/stm32F10x基本相同,只存在微小差异)
四.总结
这次实验让我更加熟练使用并且掌握了gcc编译工具,通过几个例子学会了用gcc生成静态库和动态库,还有静态库.a和动态库.so库文件的生成和使用。也了解到了编译工具集中各个软件的用途,虽然实验过程遇到一些问题,但都通过询问同学和上网查找资料得以解决,希望通过不断的实验提升我的动手能力。