【教学课件】第3章程序设计基础.ppt

上传人:牧羊曲112 文档编号:4879215 上传时间:2023-05-21 格式:PPT 页数:201 大小:656.50KB
返回 下载 相关 举报
【教学课件】第3章程序设计基础.ppt_第1页
第1页 / 共201页
【教学课件】第3章程序设计基础.ppt_第2页
第2页 / 共201页
【教学课件】第3章程序设计基础.ppt_第3页
第3页 / 共201页
【教学课件】第3章程序设计基础.ppt_第4页
第4页 / 共201页
【教学课件】第3章程序设计基础.ppt_第5页
第5页 / 共201页
点击查看更多>>
资源描述

《【教学课件】第3章程序设计基础.ppt》由会员分享,可在线阅读,更多相关《【教学课件】第3章程序设计基础.ppt(201页珍藏版)》请在三一办公上搜索。

1、第 3 章 程序设计基础,GNU集成编译环境GCC(GNU Compiler Collection)是一种面向嵌入式领域、支持多种编程语言、支持多种CPU的交叉编译工具。本章主要介绍:GCC编译过程C/C+交叉编译器arm-elf-gcc交叉汇编器 arm-elf-as 交叉连接器arm-elf-l d工程管理器make汇编语言编程混合编程,3.1 GNU GCC简介,GNU GCC是一套面向嵌入式领域的交叉编译工具,支持多种编程语言、多种优化选项并且能够支持分步编译、支持多种反汇编方式、支持多种调试信息格式,目前支持X86、ARM7、StrongARM、PPC4XX、MPC8XX、MIPS

2、R3000等多种CPU。,GNU GCC的基本功能包括:,输出预处理后的C/C+源程序(展开头文件和替换宏)输出C/C+源程序的汇编代码输出二进制目标文件生成静态库生成可执行程序转换文件格式,3.1.1 GCC 组成,1.C/C+交叉编译器arm-elf-gccarm-elf-gcc是编译的前端程序,它通过调用其他程序来实现将程序源文件编译成目标文件的功能。编译时,它首先调用预处理程序(cpp)对输入的源程序进行处理,然后调用 cc1 将预处理后的程序编译成汇编代码,最后由arm-elf-as将汇编代码编译成目标代码。arm-elf-gcc具有丰富的命令选项,可以控制编译的各个阶段,满足用户的

3、各种编译需求。,2.汇编器 arm-elf-as,arm-elf-as将汇编语言程序转换为ELF(Executable and Linking Format,执行时链接文件格式)格式的可重定位目标代码,这些目标代码同其它目标模块或函数库易于定位和链接。arm-elf-as产生一个交叉参考表和一个标准的符号表,产生的代码和数据能够放在多个区(Section)中。,3.连接器arm-elf-ld,arm-elf-ld根据链接定位文件Linkcmds中的代码区、数据区、BSS区和栈区等定位信息,将可重定位的目标模块链接成一个单一的、绝对定位的目标程序。该目标程序是ELF格式,并且可以包含调试信息。a

4、rm-elf-ld会产生一个内存映象文件Map.txt,该文件显示所有目标模块、区和符号的绝对定位地址。它也产生交叉参考列表,显示参考每个全局符号的目标模块。,arm-elf-ld支持将多个目标模块链接成一个单一的、绝对定位的目标程序,也能够依此对目标模块进行链接,这个特性称为增量链接(Incremental Linking)。假如输入文件是一个函数库,arm-elf-ld会自动从函数库装载被其它目标模块参考的函数模块。arm-elf-ld与其它链接程序相比,能提供更有帮助的诊断信息。许多链接器遇到第一个错误即放弃链接,而arm-elf-ld只要有可能都继续执行,帮助用户识别其它错误,有时甚至

5、能获得输出代码。,4.库管理器arm-elf-ar,arm-elf-ar将多个可重定位的目标模块归档为一个函数库文件。采用函数库文件,应用程序能够从该文件中自动装载要参考的函数模块,同时将应用程序中频繁调用的函数放入函数库文件中,易于应用程序的开发管理。arm-elf-ar支持ELF格式的函数库文件.,5.工程管理器MAKE,Make是用于自动编译、链接程序的实用工具,使用make后就不需要手工的编译每个程序文件。要使用make,首先要编写makefile。Makefile描述程序文件之间的依赖关系,并提供更新文件的命令。在一个程序中,可执行文件依赖于目标文件,而目标文件依赖于源文件。如果ma

6、kefile文件存在,每次修改完源程序后,用户通常所需要做的事情就是在命令行敲入“make”,然后所有的事情都由make来完成。,6.其他实用程序,目标文件格式转换工具arm-elf-objcopy支持的文件格式有H-record、S-record、ABS、BIN、COFF、ELF。例如,它能够将ELF格式文件转换为其它格式的文件,如intel H-record格式、Motorola S-record等。arm-elf-nm程序用于显示文件中的符号信息。,3.1.2 GCC编译程序的基本过程,GCC编译程序的基本过程如下:arm-elf-gcc根据输入文件的后缀来确定文件的类型,然后根据用户的

7、编译选项(包括优化选项、调试信息选项等)将其编译成相应的汇编临时文件(后缀为.s);arm-elf-as将该汇编文件编译成目标文件(后缀为.o);arm-elf-ld 根据用户的链接选项(包括指定链接命令文件等)将目标文件和各种库链接起来生成可执行文件。图3-1展示了该编译过程:,3.2 C/C+交叉编译器arm-elf-gcc,3.2.1 概述arm-elf-gcc是编译的前端程序,它通过调用其他程序来实现将程序源文件编译成目标文件。编译时它首先调用预处理程序(cpp)对输入的源程序进行处理;然后调用cc1将预处理后的程序编译成汇编代码;最后由arm-elf-as将汇编代码编译成目标代码。a

8、rm-elf-gcc具有丰富的命令选项,控制编译的各个阶段,满足用户的各种编译需求,1.命令格式,arm-elf-gcc options file在命令arm-elf-gcc后面跟一个或多个选项,选项间用空格隔开,然后跟一个或多个目标文件。例如,将test.c 编译成目标文件test.o 并且生成调试信息:arm-elf-gcc g c o test.o test.c,2.命令选项列表,输出控制选项:-c 将输入的源文件编译成目标文件-S 将C/C+文件生成汇编文件-o file 将输出内容存于文件file-pipe 在编译的不同阶段之间采用管道通讯方式-v 打印出编译过程中执行的命令-x l

9、anguage说明文件的输入类型为language,C语言选项:-ansi 支持所有ANSI C程序警告选项:-w 关闭所有警告-Wall 打开所有警告-Wimplicit 如果有隐含申明,显示警告信息-Wno-implicit 不显示对隐含申明的警告调试选项:-g 在文件中产生调试信息(调试信息的文件格式有stabs、COFF、XCOFF、DWARF),优化选项:-O0 不优化-O1 一级优化-O2 二级优化-O3 三级优化预处理选项:-E 运行C的预处理器-C 在运用-E进行预处理时不去掉注释-D macro 定义宏macro为1-D macro=defn 定义宏macro为defn,汇编

10、选项:-Wa,option 将选项option传递 给汇编器搜索路径选项:-I dir 设置搜索路径为dir-I-指定只对#include file,有效的头文件搜索目录,3.源文件类型的识别,arm-elf-gcc能够自动根据文件名后缀识别文件类型.文件名后缀和文件类型的对应关系如下:*.c C源文件*.i 经过预处理后的C源文件*.h C头文件*.ii 经过预处理后的C+源文件*.cc C+源文件*.cxx C+源文件*.cpp C+源文件*.CC+源文件*.s 不需要预处理的汇编文件*.S需要预处理的汇编文件,此外,用户可通过-x language说明文件的输入类型,此时可以不用以上的后

11、缀规则。-x language其中的language可为:c C源文件c+C+源文件c-header C头文件cpp-output 经过预处理后的C源文件c+-cpp-output 经过预处理后的C+源文件assembler 不需要预处理的汇编文件assembler-with-cpp 需要预处理的汇编文件例如,编译一个不需要预处理的C程序:arm-elf-gcc c g xcpp-output test.c-x none如果-x后面未跟任何参数,则按照文件的后缀名做相应处理。,3.2.2 命令使用,1.输出文件名的指定-o file将输出内容存于文件file,仅适用于只有一个输出文件时。例如,

12、将test.c编译成汇编程序并存放于文件test.txt:arm-elf-gcc S o test.txt test.c,2.目标文件的生成-c将输入的源文件编译成目标文件。例如,将test.c编译成test.o:arm-elf-gcc c o test.o test.c3将C/C+文件生成汇编文件-S将C/C+文件生成汇编文件。例如:将test.c编译生成汇编文件test.s:arm-elf-gcc S o test.s test.c,4.预处理文件的生成,-E只对源文件进行预处理并且缺省输出到标准输出。例如,对test.c进行预处理并将结果输出到屏幕:arm-elf-gcc E test.

13、c例如,对test.c进行预处理并将结果输出到文件test.txt:arm-elf-gcc E o test.txt test.c,5设置头文件搜索路径,头文件的引用有两种形式:一种是#include“filename”,一种是#include。前一种形式的路径搜索顺序是:当前目录、指定的搜索路径;后一种形式只搜索指定路径。,-I dir将目录dir添加到头文件搜索目录列表的第一项。通过此选项可以使用户头文件先于系统头文件被搜索到。如果同时用-I选项添加几个目录,目录被搜索时的优先级顺序为从左到右。例如,编译test.c,在当前目录和/include中搜索test.c所包含的头文件:arm-e

14、lf-gcc I./I/include c test.c,-I-I-以前用-I指定的头文件搜索目录只对#include“file”有效,对#include 无效;-I-以后指定的头文件搜索目录对以上两种形式的头文件都有效。此外,-I-会禁止对当前目录的隐含搜索,不过用户可以通过使用“-I.”使能对当前目录的搜索。,例如:在需要编译的test.c文件对头文件的引用有:#include#include“file2.h”#include“file3.h”其中,file1.h在目录/include/test下,file2.h在/include下,file3.h在当前目录下。在以下命令行中,只能搜索到f

15、ile2.h,而不 能搜索到file1.h:arm-elf-gcc I./include/test I I./include c test.c,而在以下命令行中,可以搜索到需要的两个头文件file1.h和file2.h:arm-elf-gcc I I./include I./include/test c test.c如果要搜索到file3.h,必须要添加对当前目录的搜索:arm-elf-gcc I I.I./include I./include/test c test.c实质上,上述编译命令等价于:arm-elf-gcc I.I./include I./include/test c test.

16、c 与 arm-elf-gcc I./include I./include/test c test.c,6控制警告产生,用户可以使用以-W开头的不同选项对特定警告进行设定。对于每种警告类型都有相应以-Wno-开始的选项关闭警告。例如:如果有隐含申明,显示警告信息:arm-elf-gcc c Wimplicit test.c不显示对隐含申明的警告:arm-elf-gcc c Wnoimplicit test.c常用的警告选项有:-w 关闭所有警告信息。-Wall 打开所有警告信息。,7实现优化,优化的主要目的是使编译生成的代码的尺寸更小、运行速度更快。但是在编译过程中随着优化级别的升高,编译器会

17、相应消耗更多时间和内存,而且优化生成代码的执行顺序和源代码有一定出入,因此优化选项更多地用于生成固化代码,而不用于生成调试代码。,arm-elf-gcc支持多种优化选项,总体上划分为三级优化:-O1 可以部分减小代码尺寸,对运行速度有一定的提高。较多地使用了寄存器变量,提高指令的并行度。-O2 除了解循环、函数插装和静态变量优化,几乎包含arm-elf-gcc所有优化选项。一般在生成固化代码时使用该选项较为适宜。-O3 包含-O2的所有优化,并且还包含了解循环、函数插装和静态变量优化。通常情况下,该级优化生成的代码执行速度最快,但是代码尺寸比-O2大一些。,8在命令行定义宏,-D macro定

18、义宏macro为1。-D macro=defn 定义宏macro为defn。例如:编译test.c并且预定义宏 RUN_CACHE 值为1:arm-elf-gcc c D RUN_CACHE test.c编译test.c并且预定义宏 RUN_CACHE 值为0:arm-elf-gcc c D RUN_CACHE=0 test.c,3.3 交叉连接器arm-elf-ld,3.3.1 概述arm-elf-ld根据链接定位文件Linkcmds中代码段、数据段、BSS段和堆栈段等定位信息,将可重定位的目标模块链接成一个单一的、绝对定位的目标程序,该目标程序是ELF格式,并且可以包含调试信息。arm-e

19、lf-ld可以输出一个内存映象文件,该文件显示所有目标模块、段和符号的绝对定位地址,它也产生目标模块对全局符号引用的交叉参考列表。,arm-elf-ld支持将多个目标模块链接成一个单一的、绝对定位的目标程序,也能够依次对目标模块进行链接,这个特性称为增量链接(Incremental Linking)。arm-elf-ld会自动从库中装载被调用函数所在的模块。,1命令格式,arm-elf-ld option file命令行后跟选项和可重定位的目标文件名。例如:链接的输入文件为demo.o,输出文件为demo.elf,链接的库为libxxx.a,生成内存映象文件map.txt,链接定位文件为lin

20、kcmds,则命令如下:arm-elf-ld-Map map.txt-T linkcmds-L./lib o demo.elf demo.o lxxx,2命令选项列表,-e entry指定程序入口-M输出链接信息-lar指定链接库-L dir添加搜索路径-o设置输出文件名-Tcommandfile指定链接命令文件-v显示版本信息-Map制定输出映像文件,3.3.2 命令使用,1程序入口地址-e entry以符号entry作为程序执行的入口地址,而不从默认的入口地址开始。默认入口地址的指定方式和其他指定方式的描述,参见节。例如,链接的输入文件为demo.o,输出文件为demo.elf,链接定位文

21、件为linkcmds,将入口地址设为_start,命令如下:arm-elf-ld T linkcmds e _start o demo.elf demo.o,2输出链接信息,-M在标准端口打印出符号映象表和内存分布信息。例如:链接的输入文件为demo.o,输出文件为demo.elf,在标准端口打印出符号映象表和内存分布信息,命令如下:arm-elf-ld M o demo.elf demo.o如果标准输出设置为显示器,运行命令后将在显示器上显示内存映象信息和符号映象表。,-Map mapfile将链接的符号映象表和内存分布信息输出到文件mapfile里。例如:链接的输入文件为demo.o,输出

22、文件为demo.elf,将链接的符号映象表和内存分布信息输出到文件map.txt里,命令如下:arm-elf-ld Map map.txt o demo.elf demo.o,3指定链接的库,-lar指定库文件libar.a为链接的库。可以重复使用-l来指定多个链接的库。例如:链接的输入文件为demo.o,指定libxxx.a为链接的库,输出文件为demo.elf,命令如下:arm-elf-ld o demo.elf demo.o lxxx注意:库的命名规则为libxxx.a,在-l指定库名时使用的格式为-lxxx。,4添加库和脚本文件的搜索路径,-Ldir将dir添加到搜索路径。搜索顺序按照

23、命令行中输入的顺序,并且优先于默认的搜索路径。所有在-L添加的目录中找到的-l指定的库都有效。例如:链接的输入文件为demo.o,输出文件为demo.elf,将/lib添加到库的搜索路径,命令如下:arm-elf-ld-L./lib o demo.elf demo.o,5设置输出文件的名字,-o output将输出文件名字设定为output。如果不指定输出文件名,arm-elf-ld生成文件名默认为a.out。例如:链接的输入文件为demo.o,输出文件为demo.elf,命令如下:arm-elf-ld o demo.elf demo.o,3.3.3 linkcmds连接命令文件,arm-el

24、f-ld的命令语言是一种描述性的脚本语言,它主要应用于控制:有哪些输入文件、文件的格式怎样、输出文件中的模块怎样布局、分段的地址空间怎样分布、以及未初始化的数据段怎样处理等。用命令语言写成的文件(通常称为linkcmds)具有可重用性,不必每次在命令行输入一大堆命令选项.并且对于不同的应用,只需对linkcmds进行简单的修改就可以使用。,1调用linkcmds,首先写一个链接命令文件linkcmds,然后在arm-elf-ld的命令中使用-T linkcmds参数,就能在链接时自动调用linkcmds文件例如:链接的输入文件为demo.o,输出文件为demo.elf,链接定位文件为linkc

25、mds,则命令如下:arm-elf-ld T linkcmds o demo.elf demo.o,2编写linkcmds,(1)arm-elf-ld命令语言arm-elf-ld命令语言是一系列语句的集合,包括用简单的关键字设定选项、描述输入文件及其格式、命名输出文件。其中有两种语句对于链接过程起重要作用:SECTIONS语句和MEMORY语句。SECTIONS语句用于描述输出文件中的模块怎样布局,MEMORY语句描述目标机中可以用的存储单元。,(2)表达式,在linkcmds中的表达式与C语言中的表达式类似,它们具有如下的特征:表达式的值都是“unsigned long”或者“long”类型

26、常数都是整数支持C语言中的操作符可以引用或者定义全局变量可以使用内建的函数,整数,八进制数以0开头,例如:0234;十进制数以非0的数字开头,例如:567;十六进制数以0 x或0X开头,例如:0 x16;负数以运算符-开头,例如:-102;以K,M为后缀分别表示以1024,1024*1024为单位,例如:var1=1K和var1=1024相等,var2=1M和var2=1024*1024相等。,变量名,以字母、下划线和点开头,可以包含任何字母、下划线、数字、点和连接符。变量名不能和关键字一样,如果变量名和关键字一样,或者变量名中包含空格时,必须将变量名包含在“”中.例如:“SECTION”9;

27、“with a space”“also with a space”+10;在arm-elf-ld命令语言中,空格用于界定相邻符号,例如:A-B表示一个变量名,而A-B表示一个减法的表达式。,地址记数器点号“.”,“.”是一个包含当前输出地址的计数器。因为“.”总是表示某个输出段的地址,所以总是和表达式一起在SECTIONS命令中出现。“.”可以在任何一般符号出现的地方出现,对“.”的赋值将引起计数器所指位置的移动,而计数器位置不能反向移动。,例如:SECTIONSoutput:file1(.text).=.+1000;file2(.text).+=1000;file3(.text)=0 x12

28、34;,在左面的例子中,在file1(.text)与file2(.text)之间被空出了1000个字节的空间,file2(.text)与file3(.text)之间也被空出了1000个字节的空间,而0 x1234为该分段的空间空隙的填充值。,可以将“.”赋给变量;也可以对“.”赋值。例如:data_start=.;.=.+2000;,(3)linkcmds的结构,linkcmds文件主要由四个部分组成:程序入口说明:用于指定程序运行时所需要执行的第一条指令的地址。程序头说明:生成目标文件类型为ELF,可以指定详细的程序头信息。内存布局的说明:用于规划内存的布局,将内存空间划分为不同的部分。分段

29、的分步说明:详细指明各个分段的构成以及分段的定位地址和装载地址。其中和的部分不能被省略。,(4)对程序入口的说明,arm-elf-ld命令语言有一条特定命令用于指定输出文件中第一条可执行指令,即程序的入口点。该命令格式如下:ENTRY(symbol)其中ENTRY是保留字,symbol表示程序的入口地址,通常是用一个全局地址标号(label)来表示入口地址。例如,在程序中的开始地方有一标号:.global demo_startdemo_start:movl$_stack_top,%esp,那么在linkcmds中可以用下面的方式说明程序的入口:ENTRY(demo_start);该命令可以作为

30、单独的一条命令放在linkcmds的任何位置,也可以放在SECTIONS内关于段的定义部分,都对布局起作用。指定入口地址的方式还有很多,现在按优先级递减的顺序描述如下:用-e选项指定入口地址在linkcmds里用ENTRY(symbol)指令变量start的值,如果有变量start.text段第一字节的地址,如果存在0地址,(5)对程序头的说明,ELF格式文件需要使用程序头,它用于描述程序应该怎么被装入内存。在默认情况下,arm-elf-ld可以自己生成一个程序头,用户也可以用PHDRS自己编写程序头,当运用该命令时,arm-elf-ld不会生成默认的程序头。注意:如果没有特殊要求,建议用户不

31、要自己写程序头。,PHDRSname type FILEHDR PHDRS AT(address)FLAGS(flags);其中PHDRS、FILEHDR、AT、FLAGS都是关键字。name表示段(Segment)的名字,而该段(Segment)装入的内容由SECTIONS中对分段(Section)的描述决定,例如:SECTIONSsecname start BLOCK(align)(NOLOAD):AT(ldadr)contents region:phdr=fill,因此PHDRS中的name应该和SECTIONS中的phdr保持一致。type表示段的类型,可以为下面描述的任意一种类型(括

32、号内表示关键字的值):PT_NULL(0)空程序头PT_LOAD(1)描述一个可装入的段PT_DYNAMIC(2)表示包含动态链接信息的段PT_INTERP(3)表示该段包含程序解释器的名字PT_NOTE(4)表示包含注释信息的段PT_SHLIB(5)一个保留的程序头PT_PHDR(6)表示该段可能包含程序头的描述信息expression 用数值表示一个程序头的类型,该类型没有对应的关键字,FILEHDR表示在段中包含ELF文件头的信息。PHDRS表示在段中还要包含程序头本身的信息。AT(address)表示该段的起始地址,若在SECTIONS中也有AT时,程序头中定义的AT优先。例如:PHD

33、RSheaders PT_PHDR PHDRS;interp PT_INTERP;text PT_LOAD FILEHDR PHDRS;data PT_LOAD;dynamic PT_DYNAMIC;,SECTIONS.=SIZEOF_HEADERS;.interp:*(.interp):text:interp.text:*(.text):text.rodata:*(.rodata)/*defaults to:text*/.=.+0 x1000;/*move to a new page in memory*/.data:*(.data):data.dynamic:*(.dynamic):dat

34、a:dynamic.,在上面的例子中,定义了5个段:headers申明一个程序头段;interp申明一个段,段中包含了程序解释器的名字;text申明一个可被下载的段,并且包含了文件的头信息和各段的信息;data申明一个可被下载的段;dynamic申明一个包含动态链接信息的段;,在SECTIONS中可以看到,有的分段同时属于两个段,实质上是这两个段占用同一空间。.rodata也属于.text段是由于它的上一个分段属于.text段,而.rodata又没有指明归属段。注意:如果没有特殊要求,建议用户不要自己写程序头。,(6)对内存布局的说明,arm-elf-ld的默认配置允许将输出程序定位到任何可用

35、内存。用户也可以用MEMORY命令对内存进行配置。MEMORY命令可以定义目标机内存段的位置和大小,当装载的程序块大小超出指定的内存段大小时,arm-elf-ld会提示出错,而不会自动寻找可用的内存段,这样可以避免内存分配错误。,定义内存段的方式:MEMORYname(attr):ORIGIN=origin,LENGTH=lenname表示内存段的名字,可以使用任何变量名,但是不能和已有变量名、文件名和分段名(section name)冲突。attr没有实际的用途,可省略。origin(可简写为:org或者o)表示内存段的起始位置。Length(可简写为:len或者l)表示内存段的长度.,ME

36、MORYrom:ORIGIN=0 x3f80000,LENGTH=512Kram:org=0,l=1M 表示定义了两个内存段:rom内存段,起始地址为0 x3f80000,长度为512K;ram内存段,起始地址为0,长度为1M。,(7)对分段的说明,SECTIONS命令控制如何正确地将输入分段定位到输出分段,包括在输出文件中的顺序,和输入分段在输出分段中的定位。如果不用SECTIONS命令,arm-elf-ld将对每个输入分段生成相同名字的输出分段,分段的顺序由输入文件中遇到的分段的先后顺序决定。,SECTIONS命令的格式:SECTIONS.secname start BLOCK(align

37、)(NOLOAD):AT(ldadr)contents region:phdr=fill.其中secname和contents都是必须有的。secname表示输出分段的名字,受输出格式的限制,一些输出格式对段名有限制,例如a.out只允许.text,.data或.bss的分段名存在.另外arm-elf-ld不输出空的分段。,start,BLOCK(align),(NOLOAD),AT(ldadr),region,:phdr,=fill都是可选项:Start 表示分段的起始地址,该地址被称为重定位地址;BLOCK(align)表示分段以align对齐;(NOLOAD)表示该段不能被装载;AT(l

38、dadr)表示该分段装入的起始地址为ldadr,当没有该参数时分段的装入地址和重定位地址相同;,region 表示该分段地址空间在region所定义的范围内,region就是在MEMORY命令中定义的内存段名字;:phdr 表示该分段的装载地址空间在phdr定义的范围内,phdr就是在程序头中定义的段名字;=fill 表示在该分段的空间空隙的填充值。,contents表示具体的分段内容,主要描述该输出分段中包含有输入文件中的哪些分段。常见的分段名如下:.text 表示代码段.data 初始化了的数据段.bss 未初始化的数据段.rodata 不可写的数据段COMMON 未初始化的数据段,用户在

39、汇编语言程序中可以自定义分段名,如:mycode、mydata之类。在C语言文件编译成目标文件后,通常包含有.text、.data、COMMON、.rodata段。其中.rodata表示不可写的数据段,通常包含在C语言程序中定义的一些常量,如const char version_string=“Lambda x86/fpm”之类。,contents可用格式:,filenamefilename(section)filename(section,section,)filename(section section)和针对所有文件的:*(section)*(section,section,)*(sec

40、tion section),如果在用“*”指定所有文件时,以前已经使用filename指定过一些文件,那么“*”表示剩下的文件:filename(COMMON)*(COMMON)指定输入文件中名为COMMON的分段里未初始化的数据在输出分段中的位置。下面举例说明contents中的具体内容及编写方法。,下面举例说明contents中的具体内容及编写方法。例如:.text 0:file1.o file2.o file3.o 表示将file1.o、file2.o、file3.o中的所有分段都放在输出文件的.text段中。例如:.text 0:*(.text);表示将所有输入文件中的.text分段都

41、放在输出文件的.text段中。,例如:.text 0:file1.o(.text);file2.o(.text);file3.o(.text);表示将file1.o、file2.o、file3.o中的.text段都放在输出文件的.text段中。,例如:text1:file1.o(.text);text2:*(.text);表示将file1.o中的.text段放在输出文件的text1段中,而其他输入文件的.text段都放在输出文件的text2段。,(8)注释,arm-elf-ld语言中的注释和C语言一样。例如:/*comments*/,3.4 工程管理器 MAKE,3.4.1 概述make是用于

42、自动编译、链接程序的实用工具。使用make后就不需要手工编译每个程序文件。,要使用make,首先要编写makefile,makefile描述程序文件之间的依赖关系以及提供更新文件的命令。典型地,在一个程序中,可执行文件依赖于目标文件,而目标文件依赖于源文件。如果makefile文件存在,每次修改完源程序后,用户通常所需要做的事情就是在命令行敲入“make”,然后所有的事情都由make来完成。,1命令格式,make-f makefile option targetmake命令后跟-f选项,指定makefile的名字为makefile;option表示make的一些选项;target是make指定

43、的目标,在将详细说明。例如:makefile的名字是my_hello_make:make f my_hello_make,2命令选项列表,-f指定makefile-e使环境变量优先于makefile的变量-I dir设定搜索目录-i忽略make过程中所有错误-n只显示执行过程,而不真正执行-r使隐含规则无效-w显示工作目录-C dir读取makefile设置的工作目录-s不显示执行的命令,命令使用,makefile文件用来告诉make需要做的事情,通常指怎样编译、怎样链接一个程序。以C语言程序为例:在用make重新编译的时候,如果一个头文件已被修改,则包含这个头文件的所有C源代码文件都必须被重

44、新编译。而每个目标文件都与C的源代码文件有关,如果有源代码文件被修改过,则所有目标文件都必须被重新链接生成最后的结果。编写一个makefile将在节详细介绍。,1指定makefile,-f makefile用该选项指定makefile的名字为makefile。如果make中多次使用-f指定多个makefile,则所有makefile将链接起来作为最后的makefile。如果不指定makefile,make默认的makefile依次为“makefile”、“Makefile”。例如:make f my_hello_make,2使环境变量优先于makefile文件中的变量,-e使环境变量优先于ma

45、kefile文件中的变量。例如:make e,3指定包含文件的搜索路径,-I dir指定在解析makefile文件中的.include时的搜索路径为dir。如果有多个路径,将按输入顺序依次查找。例如:make I/include/mk,4忽略错误-i忽略make执行过程中的所有错误。例如:make i 5显示命令的执行过程-n只显示命令的执行过程而不真正执行。例如:make n,6使隐含规则无效-r使make的隐含规则无效,清除后缀名规则中默认的后缀清单。例如:make r7显示执行过程中的工作目录-w显示make执行过程中的工作目录。例如:make w,8读取makefile文件前设置工作目

46、录,-C dir在读取makefile文件以前将工作目录改变为dir,完成make后改回原来的目录。如果在一次make中使用多个-C选项,每个选项都和前面一个有关系。“-C dir0/-C dir1”与“-C dir0/dir1”等价.例如:make C bsp,9不显示所执行的命令,-s运行make时用选项-s可以不显示执行的命令,只显示生成的结果文件。例如:make s,3.4.3 编写一个makefile,1.makefile的结构makefile文件包含:显式规则隐含规则变量定义指令注释,2.编写makefile中的规则,makefile中规则的格式如下:targets:depende

47、nciescommand或者targets:dependencies;commandcommandtargets 指定目标名,通常是一个程序产生的目标文件名,也可能是执行一个动作的名字,名字之间用空格隔开。dependency 描述产生target所需的文件,一个target通常依赖于多个dependency。command 用于指定该规则的命令。注意:command必须以TAB键开头。如果某一行过长可以分作两行,用连接。,例如:smcinit:smc.o config.oarm-elf-ar ruvs o smcinit.a smc.o config.osmc.o:smc.c include

48、.harm-elf-gcc c o smc.o smc.cconfig.o:config.c include.harm-elf-gcc c o config.o config.cclean:rm*.o表示目标名的有smcinit、smc.o、config.o。smcinit依赖于smc.o和config.o,而smc.o又依赖于smc.c和include.h,config.o依赖于config.o和include.h.各目标分别由命令arm-elf-ar ruvs o smcinit.a smc.o config.o;arm-elf-gcc c o smc.o smc.c;arm-elf-gc

49、c c o config.o config.c来生成。clean为一动作名,删除所有后缀为.o的文件。,3.make调用makefile中的规则,在默认情况下,make运行不是以“.”开头的第一条规则。在上面的例子中,make默认执行的是规则smcinit,此时只需要输入命令:makemake将读入makefile,然后执行第一条规则,例子中该规则是链接目标文件生成库,因此必须执行规则smcinit依赖的规则smc.o和config.o。在执行过程中将自动更新他们所依赖的文件。有些规则不是被依赖的规则,需要make指定才能被运行,如上面的例子中的clean规则可以这样执行:make clean

50、这两种方式的结果一样。只是第一种方式没指明目标名,第二种方式指明了目标名。,4.设置makefile中文件的搜索路径,在makefile中,可以通过给VPATH赋值来设置规则中目标文件和依赖文件的搜索目录。make首先搜索当前目录,如果未找到依赖的文件,make将按照VPATH中给的目录依次搜索。VPATH对makefile中所有文件都有效。例如:demo.o:demo.c demo.hdemo.c在目录/c/demo/中,demo.h在目录/c/demo/head/中,则可以给VPATH变量赋值:VPATH:=/c/demo/c/demo/head或者VPATH:=/c/demo:/c/de

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号