自学内容网 自学内容网

系统编程-00预科

一、程序的概念

        一般的讲,程序是一系列有序指令的集合,目的是告诉计算机如何完成某些指定的操作或者如何解决某个问题。

二、计算机语言的发展历程

        计算机早期程序采用机器语言设计,但是由于开发效率较低,所以后面设计出汇编语言,但是由于汇编语言的汇编指令较多,并且不同的公司及组织对研发平台设计出不同的汇编指令集,而这些汇编指令集并不兼容,所以为了进一步提高开发效率和降低开发难度,就设计出高级语言,比如面向过程编程的C语言,和面向对象编程的C++以及其他编程语言。

三、程序的运行

        程序只是开发人员为了实现某些需求设计出来的文本,是存储在计算机的磁盘中的,想要得到程序的运行结果,是需要使用编译器等工具对程序进行编译等一系列操作,目的是把程序转换为可执行文件,可执行文件内部其实就是对应平台可以识别的指令和数据的集合,可执行文件得到运行就是计算机的中央处理器CPU对可执行文件内部的指令进行处理,对可执行文件内部的数据进行运算的过程。

四、指令和数据的执行流程

        大家想要了解程序中指令和数据具体的执行流程,需要熟悉计算机组成原理以及汇编语言,其中计算机组成部分一般遵循冯诺依曼结构,也就是由控制器、运算器、存储器、输入设备、输出设备五个部分组成。

源文件(xxx.c)--->预处理(-E xxx.i)--->编译(-S xxx.s)--->汇编(-c xxx.o)--->链接(L)--->可执行文件

        CPU只与内存打交道,程序和指令通过输入设备写在文件当中,存储于外存;

        程序运行后,才载入内存中,由CPU的运算器对其指令进行处理,对其数据进行运算;

        然后将处理结果通过CPU的控制器传输给输出设备进行打印。

五、程序的编译过程

        一般在编写出程序之后,并不能直接运行,而是需要把程序通过编译器进行编译,生成可执行文件才能运行。而对于嵌入式学习,一般都是在Linux系统下使用GCC编译器对程序进行编译。

        GCC编译器是Linux系统默认的C/C++编译器,大部分Linux发行版本中都是默认安装的。GCC编译器主要以Linux命令的形式在shell终端中使用,所以需要大家掌握关于GCC编译器的相关参数。

可通过该参数help获取gcc 编译器的使用帮助 gcc --help

C语言程序编译过程:

  • 1、源程序: 用户通过输入设备编写源程序
  • 2、预处理 : gcc -E xxx.c -o xxx.i GCC编译器调用预处理器cpp对程序进行预处理。 对源文件中的所有预处理(以#开头的预处理语句)指令进行解释: #include 文件包含 #define 宏定义 #if 条件编译 注意:对其预处理指令进行解释,如将包含文件按拷贝进来,覆盖原来的#include语句 将所有的宏进行展开 所有的条件编译语句被执行 GCC还会把所有的注释删除掉,添加必要的调试信息
  • 3、编译: gcc -S xxx.i -o xxx.s 对预处理后的xxx.i文件进一步翻译,检查语法、词法的分析,最终生成对应硬件平台的汇编文件。 常用平台有:X86平台使用gcc编译器,ARM平台使用交叉编译工具arm-linux-gcc
  • 4、汇编: gcc -c xxx.s -o xxx.o GCC编译器调用汇编器as将汇编文件翻译为可重定位文件 即将xxx.s文件的汇编代码翻译为相应的指令
  • 5、链接 gcc xxx.o -o xxx -lc -lgcc(-lc -lgcc) 经过汇编后生成的xxx.o文件是ELF格式的可重定位文件 虽然已经生成了指令流,但是需要重定位函数地址等 所以需要链接系统提供的标准C库和其他gcc基本库文件等 且还要把其他的.o文件一起进行链接。 -lc -lgcc 是默认的可以省略 l是lib的缩写
  • 6、可执行文件 生成的a.out可执行文件
预处理:gcc -E xxx.c -o xxx.i
编  译:gcc -S xxx.i -o xxx.s
汇  编:gcc -c xxx.s -o xxx.o
链  接;gcc xxx.o -o xxx
也可以一步完成四个步骤:gcc xxx.c -o xxx

六、程序的格式

        一般对源文件进行编译和汇编之后,就会得到对应的目标文件xxx.o,目标文件也被称为可重定位文件,就是指还未完成链接的中间文件,用户可以把这些目标文件制作成在Linux系统下使用的静态库libxxx.a或者动态库libxxx.so。  

        其实目标文件和可执行文件的内容和结构非常相似,所以Linux系统下把目标文件xxx.o和可执行文件都称为ELF文件。ELF指的是Executable Linkable Format的缩写,中文翻译为可执行可链接格式。

注意:可以在linux系统中利用查看文件格式的指令: file 查阅目标文件和可执行文件的区别:

七、目标文件

思考:还未完成链接的目标文件中存储了哪些内容,以及如何查看目标文件中的内容信息???

回答:目标文件中的内容至少有编译后的机器指令代码、数据。除了这些内容以外,目标文件中还包括了链接时所需要的一些信息,比如符号表、调试信息、字符串等。一般目标文件将这些信息按不同的属性,以“节”(Section)的形式存储,有时候也叫“段”(Segment),一般情况下,它们都表示一个一定长度的区域,基本上不加以区别。

程序源代码编译后的机器指令经常被放在代码段(Code Section)里,代码段常见的名字有“.code”或“.text”。

全局变量和局部静态变量数据经常放在数据段(Data Section),数据段一般名字都叫“.data”。

注意:linux系统的GCC编译套件有一款工具叫做objdump,可以查看目标文件内部的数据!

        数据段中有一个叫做.bss段, bss以前其实是汇编伪指令,作用是为某些数据预留一块空间,bss其实是Block Started by Symbol,也就是用于存储未被初始化的全局变量和静态局部变量,但是在程序编译阶段是没有分配空间的,在程序运行时会得到空间。

八、可执行文件

常用的段名

说 明

.rodatal

这种段里存放的是只读数据,比如字符串常量、全局const变量。跟".rodata"一样

.comment

存放的是编译器版本信息,比如字符串:“GCC:(GNU)4.2.0”

.debug

调试信息

.dynamic

动态链接信息

.hash

符号哈希表

.line

调试时的行号表,即源代码行号与编译后指令的对应表

.note

额外的编译器信息。比如程序的公司名、发布版本号等

.strtab

String Table.字符串表,用于存储ELF文件中用到的各种字符串

.symtab

Symbol Table.符号表

.shstrtab

Section String Table.段名表

.plt

动态链接的跳转表和全局入口表

.init

程序初始化与终结代码段。

        另外,objdump工具也可以实现把可执行文件进行反汇编; 可以把得到的反汇编代码重定向到某个文本中进行查看。 “objdump -D demo >> xxx.txt”


原文地址:https://blog.csdn.net/qq_59111928/article/details/140576644

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!