版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
嵌入式程序设计基础GCC编译过程CC交叉编译器armelfgcc工程管理器第1页/共202页GNU集成编译环境GCC(GNUCompilerCollection)是一种面向嵌入式领域、支持多种编程语言、支持多种CPU的交叉编译工具。本章主要介绍:GCC编译过程C/C++交叉编译器arm-elf-gcc交叉汇编器arm-elf-as交叉连接器arm-elf-ld工程管理器make汇编语言编程混合编程第2页/共202页3.1GNUGCC简介GNUGCC是一套面向嵌入式领域的交叉编译工具,支持多种编程语言、多种优化选项并且能够支持分步编译、支持多种反汇编方式、支持多种调试信息格式,目前支持X86、ARM7、StrongARM、PPC4XX、MPC8XX、MIPSR3000等多种CPU。第3页/共202页GNUGCC的基本功能包括:输出预处理后的C/C++源程序(展开头文件和替换宏)输出C/C++源程序的汇编代码输出二进制目标文件生成静态库生成可执行程序转换文件格式第4页/共202页3.1.1GCC组成1.C/C++交叉编译器arm-elf-gcc arm-elf-gcc是编译的前端程序,它通过调用其他程序来实现将程序源文件编译成目标文件的功能。 编译时,它首先调用预处理程序(cpp)对输入的源程序进行处理,然后调用cc1将预处理后的程序编译成汇编代码,最后由arm-elf-as将汇编代码编译成目标代码。
arm-elf-gcc具有丰富的命令选项,可以控制编译的各个阶段,满足用户的各种编译需求。第5页/共202页2.
汇编器arm-elf-asarm-elf-as将汇编语言程序转换为ELF(ExecutableandLinkingFormat,执行时链接文件格式)格式的可重定位目标代码,这些目标代码同其它目标模块或函数库易于定位和链接。arm-elf-as产生一个交叉参考表和一个标准的符号表,产生的代码和数据能够放在多个区(Section)中。第6页/共202页3.连接器arm-elf-ldarm-elf-ld根据链接定位文件Linkcmds中的代码区、数据区、BSS区和栈区等定位信息,将可重定位的目标模块链接成一个单一的、绝对定位的目标程序。该目标程序是ELF格式,并且可以包含调试信息。arm-elf-ld会产生一个内存映象文件Map.txt,该文件显示所有目标模块、区和符号的绝对定位地址。它也产生交叉参考列表,显示参考每个全局符号的目标模块。第7页/共202页arm-elf-ld支持将多个目标模块链接成一个单一的、绝对定位的目标程序,也能够依此对目标模块进行链接,这个特性称为增量链接(IncrementalLinking)。假如输入文件是一个函数库,arm-elf-ld会自动从函数库装载被其它目标模块参考的函数模块。arm-elf-ld与其它链接程序相比,能提供更有帮助的诊断信息。许多链接器遇到第一个错误即放弃链接,而arm-elf-ld只要有可能都继续执行,帮助用户识别其它错误,有时甚至能获得输出代码。第8页/共202页4.库管理器arm-elf-ararm-elf-ar将多个可重定位的目标模块归档为一个函数库文件。采用函数库文件,应用程序能够从该文件中自动装载要参考的函数模块,同时将应用程序中频繁调用的函数放入函数库文件中,易于应用程序的开发管理。arm-elf-ar支持ELF格式的函数库文件.第9页/共202页5.工程管理器MAKE Make是用于自动编译、链接程序的实用工具,使用make后就不需要手工的编译每个程序文件。要使用make,首先要编写makefile。
Makefile描述程序文件之间的依赖关系,并提供更新文件的命令。在一个程序中,可执行文件依赖于目标文件,而目标文件依赖于源文件。如果makefile文件存在,每次修改完源程序后,用户通常所需要做的事情就是在命令行敲入“make”,然后所有的事情都由make来完成。第10页/共202页6.其他实用程序目标文件格式转换工具arm-elf-objcopy支持的文件格式有H-record、S-record、ABS、BIN、COFF、ELF。例如,它能够将ELF格式文件转换为其它格式的文件,如intelH-record格式、MotorolaS-record等。arm-elf-nm程序用于显示文件中的符号信息。第11页/共202页3.1.2GCC编译程序的基本过程GCC编译程序的基本过程如下:arm-elf-gcc根据输入文件的后缀来确定文件的类型,然后根据用户的编译选项(包括优化选项、调试信息选项等)将其编译成相应的汇编临时文件(后缀为.s);arm-elf-as将该汇编文件编译成目标文件(后缀为.o);arm-elf-ld根据用户的链接选项(包括指定链接命令文件等)将目标文件和各种库链接起来生成可执行文件。图3-1展示了该编译过程:第12页/共202页3.2C/C++交叉编译器arm-elf-gcc3.2.1概述arm-elf-gcc是编译的前端程序,它通过调用其他程序来实现将程序源文件编译成目标文件。编译时它首先调用预处理程序(cpp)对输入的源程序进行处理;然后调用cc1将预处理后的程序编译成汇编代码;最后由arm-elf-as将汇编代码编译成目标代码。arm-elf-gcc具有丰富的命令选项,控制编译的各个阶段,满足用户的各种编译需求
第13页/共202页1.命令格式arm-elf-gcc[options]file…在命令arm-elf-gcc后面跟一个或多个选项,选项间用空格隔开,然后跟一个或多个目标文件。例如,将test.c编译成目标文件test.o并且生成调试信息:arm-elf-gcc–g–c–otest.otest.c第14页/共202页2.命令选项列表输出控制选项:-c 将输入的源文件编译成目标文件-S 将C/C++文件生成汇编文件-ofile将输出内容存于文件file-pipe在编译的不同阶段之间采用管道通讯方式-v 打印出编译过程中执行的命令-xlanguage 说明文件的输入类型为language第15页/共202页C语言选项:-ansi
支持所有ANSIC程序警告选项:-w关闭所有警告-Wall打开所有警告-Wimplicit如果有隐含申明,显示警告信息-Wno-implicit不显示对隐含申明的警告调试选项:-g在文件中产生调试信息(调试信息的文件格式有stabs、COFF、XCOFF、DWARF)第16页/共202页优化选项:-O0不优化-O1一级优化-O2二级优化-O3三级优化预处理选项:-E运行C的预处理器-C在运用-E进行预处理时不去掉注释-Dmacro定义宏macro为1-Dmacro=defn定义宏macro为defn第17页/共202页汇编选项:-Wa,option
将选项option传递给汇编器搜索路径选项:-Idir设置搜索路径为dir-I-指定只对#include"file",有效的头文件搜索目录第18页/共202页3.源文件类型的识别arm-elf-gcc能够自动根据文件名后缀识别文件类型.文件名后缀和文件类型的对应关系如下:*.c ——C源文件*.i ——经过预处理后的C源文件*.h ——C头文件*.ii ——经过预处理后的C++源文件*.cc ——C++源文件*.cxx ——C++源文件*.cpp ——C++源文件*.C ——C++源文件*.s ——不需要预处理的汇编文件*.S ——需要预处理的汇编文件第19页/共202页此外,用户可通过-xlanguage说明文件的输入类型,此时可以不用以上的后缀规则。-xlanguage其中的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–x cpp-outputtest.c-xnone如果-x后面未跟任何参数,则按照文件的后缀名做相应处理。第20页/共202页3.2.2命令使用1.输出文件名的指定-ofile将输出内容存于文件file,仅适用于只有一个输出文件时。例如,将test.c编译成汇编程序并存放于文件test.txt:arm-elf-gcc–S–otest.txttest.c第21页/共202页2.目标文件的生成
-c将输入的源文件编译成目标文件。例如,将test.c编译成test.o:arm-elf-gcc–c–otest.otest.c3.将C/C++文件生成汇编文件
-S将C/C++文件生成汇编文件。例如:将test.c编译生成汇编文件test.s:arm-elf-gcc–S–otest.stest.c第22页/共202页4.预处理文件的生成-E只对源文件进行预处理并且缺省输出到标准输出。例如,对test.c进行预处理并将结果输出到屏幕:arm-elf-gcc–Etest.c例如,对test.c进行预处理并将结果输出到文件test.txt:arm-elf-gcc–E–otest.txttest.c第23页/共202页5.设置头文件搜索路径头文件的引用有两种形式:一种是#include“filename”,一种是#include<filename>。
前一种形式的路径搜索顺序是:当前目录、指定的搜索路径;后一种形式只搜索指定路径。第24页/共202页-Idir将目录dir添加到头文件搜索目录列表的第一项。通过此选项可以使用户头文件先于系统头文件被搜索到。如果同时用-I选项添加几个目录,目录被搜索时的优先级顺序为从左到右。例如,编译test.c,在当前目录和/include中搜索test.c所包含的头文件:arm-elf-gcc–I./–I/include–ctest.c第25页/共202页-I--I-以前用-I指定的头文件搜索目录只对#include“file”有效,对#include<file>无效;-I-以后指定的头文件搜索目录对以上两种形式的头文件都有效。此外,-I-会禁止对当前目录的隐含搜索,不过用户可以通过使用“-I.”使能对当前目录的搜索。第26页/共202页例如:在需要编译的test.c文件对头文件的引用有:
#include<file1.h> #include“file2.h” #include“file3.h”
其中,file1.h在目录/include/test下,file2.h在/include下,file3.h在当前目录下。在以下命令行中,只能搜索到file2.h,而不能搜索到file1.h:arm-elf-gcc–I./include/test–I––I./include–ctest.c第27页/共202页而在以下命令行中,可以搜索到需要的两个头文件file1.h和file2.h:
arm-elf-gcc–I––I./include–I./include/test–ctest.c如果要搜索到file3.h,必须要添加对当前目录的搜索:
arm-elf-gcc–I––I.–I./include–I./include/test–ctest.c实质上,上述编译命令等价于:arm-elf-gcc–I.–I./include–I./include/test–ctest.c
与
arm-elf-gcc–I./include–I./include/test–ctest.c第28页/共202页6.控制警告产生用户可以使用以-W开头的不同选项对特定警告进行设定。对于每种警告类型都有相应以-Wno-开始的选项关闭警告。例如:如果有隐含申明,显示警告信息:arm-elf-gcc–c–Wimplicittest.c不显示对隐含申明的警告:arm-elf-gcc–c–Wno–implicittest.c常用的警告选项有:-w
关闭所有警告信息。-Wall
打开所有警告信息。第29页/共202页7.实现优化优化的主要目的是使编译生成的代码的尺寸更小、运行速度更快。但是在编译过程中随着优化级别的升高,编译器会相应消耗更多时间和内存,而且优化生成代码的执行顺序和源代码有一定出入,因此优化选项更多地用于生成固化代码,而不用于生成调试代码。第30页/共202页arm-elf-gcc支持多种优化选项,总体上划分为三级优化:-O1
可以部分减小代码尺寸,对运行速度有一定的提高。较多地使用了寄存器变量,提高指令的并行度。-O2
除了解循环、函数插装和静态变量优化,几乎包含arm-elf-gcc所有优化选项。一般在生成固化代码时使用该选项较为适宜。-O3
包含-O2的所有优化,并且还包含了解循环、函数插装和静态变量优化。通常情况下,该级优化生成的代码执行速度最快,但是代码尺寸比-O2大一些。第31页/共202页8.在命令行定义宏-Dmacro
定义宏macro为1。-Dmacro=defn
定义宏macro为defn。例如:编译test.c并且预定义宏RUN_CACHE值为1:arm-elf-gcc–c–DRUN_CACHEtest.c编译test.c并且预定义宏RUN_CACHE值为0:arm-elf-gcc–c–DRUN_CACHE=0test.c第32页/共202页
3.3交叉连接器arm-elf-ld3.3.1概述arm-elf-ld根据链接定位文件Linkcmds中代码段、数据段、BSS段和堆栈段等定位信息,将可重定位的目标模块链接成一个单一的、绝对定位的目标程序,该目标程序是ELF格式,并且可以包含调试信息。arm-elf-ld可以输出一个内存映象文件,该文件显示所有目标模块、段和符号的绝对定位地址,它也产生目标模块对全局符号引用的交叉参考列表。第33页/共202页arm-elf-ld支持将多个目标模块链接成一个单一的、绝对定位的目标程序,也能够依次对目标模块进行链接,这个特性称为增量链接(IncrementalLinking)。
arm-elf-ld会自动从库中装载被调用函数所在的模块。第34页/共202页1.命令格式arm-elf-ld[option]file…命令行后跟选项和可重定位的目标文件名。例如:链接的输入文件为demo.o,输出文件为demo.elf,链接的库为libxxx.a,生成内存映象文件map.txt,链接定位文件为linkcmds,则命令如下:arm-elf-ld-Mapmap.txt-Tlinkcmds-L./lib–odemo.elfdemo.o–lxxx第35页/共202页2.命令选项列表-eentry 指定程序入口-M 输出链接信息-lar 指定链接库-Ldir 添加搜索路径-o 设置输出文件名-Tcommandfile 指定链接命令文件-v 显示版本信息-Map 制定输出映像文件第36页/共202页3.3.2命令使用1.程序入口地址-eentry以符号entry作为程序执行的入口地址,而不从默认的入口地址开始。默认入口地址的指定方式和其他指定方式的描述,参见3.3.3节。例如,链接的输入文件为demo.o,输出文件为demo.elf,链接定位文件为linkcmds,将入口地址设为_start,命令如下:arm-elf-ld–Tlinkcmds–e_start–odemo.elfdemo.o第37页/共202页2.输出链接信息-M在标准端口打印出符号映象表和内存分布信息。例如:链接的输入文件为demo.o,输出文件为demo.elf,在标准端口打印出符号映象表和内存分布信息,命令如下:arm-elf-ld–M–odemo.elfdemo.o如果标准输出设置为显示器,运行命令后将在显示器上显示内存映象信息和符号映象表。第38页/共202页-Mapmapfile将链接的符号映象表和内存分布信息输出到文件mapfile里。例如:链接的输入文件为demo.o,输出文件为demo.elf,将链接的符号映象表和内存分布信息输出到文件map.txt里,命令如下:arm-elf-ld–Mapmap.txt–odemo.elfdemo.o第39页/共202页3.指定链接的库-lar指定库文件libar.a为链接的库。可以重复使用-l来指定多个链接的库。例如:链接的输入文件为demo.o,指定libxxx.a为链接的库,输出文件为demo.elf,命令如下:arm-elf-ld–odemo.elfdemo.o–lxxx注意:库的命名规则为libxxx.a,在-l指定库名时使用的格式为-lxxx。第40页/共202页4.添加库和脚本文件的搜索路径-Ldir将dir添加到搜索路径。搜索顺序按照命令行中输入的顺序,并且优先于默认的搜索路径。所有在-L添加的目录中找到的-l指定的库都有效。例如:链接的输入文件为demo.o,输出文件为demo.elf,将/lib添加到库的搜索路径,命令如下:arm-elf-ld-L./lib–odemo.elfdemo.o第41页/共202页5.设置输出文件的名字-ooutput将输出文件名字设定为output。如果不指定输出文件名,arm-elf-ld生成文件名默认为a.out。例如:链接的输入文件为demo.o,输出文件为demo.elf,命令如下:arm-elf-ld–odemo.elfdemo.o第42页/共202页3.3.3linkcmds连接命令文件arm-elf-ld的命令语言是一种描述性的脚本语言,它主要应用于控制:有哪些输入文件、文件的格式怎样、输出文件中的模块怎样布局、分段的地址空间怎样分布、以及未初始化的数据段怎样处理等。用命令语言写成的文件(通常称为linkcmds)具有可重用性,不必每次在命令行输入一大堆命令选项.并且对于不同的应用,只需对linkcmds进行简单的修改就可以使用。第43页/共202页1.调用linkcmds首先写一个链接命令文件linkcmds,然后在arm-elf-ld的命令中使用-Tlinkcmds参数,就能在链接时自动调用linkcmds文件.例如:链接的输入文件为demo.o,输出文件为demo.elf,链接定位文件为linkcmds,则命令如下:arm-elf-ld–Tlinkcmds–odemo.elfdemo.o第44页/共202页2.编写linkcmds(1)arm-elf-ld命令语言arm-elf-ld命令语言是一系列语句的集合,包括用简单的关键字设定选项、描述输入文件及其格式、命名输出文件。其中有两种语句对于链接过程起重要作用:SECTIONS语句和MEMORY语句。SECTIONS语句用于描述输出文件中的模块怎样布局,MEMORY语句描述目标机中可以用的存储单元。第45页/共202页(2)表达式在linkcmds中的表达式与C语言中的表达式类似,它们具有如下的特征:表达式的值都是“unsignedlong”或者“long”类型常数都是整数支持C语言中的操作符可以引用或者定义全局变量可以使用内建的函数第46页/共202页①整数八进制数以‘0’开头,例如:0234;十进制数以非0的数字开头,例如:567;十六进制数以‘0x’或‘0X’开头,例如:0x16;负数以运算符‘-’开头,例如:-102;以K,M为后缀分别表示以1024,1024*1024为单位,例如:var1=1K和var1=1024相等,var2=1M和var2=1024*1024相等。第47页/共202页②变量名以字母、下划线和点开头,可以包含任何字母、下划线、数字、点和连接符。变量名不能和关键字一样,如果变量名和关键字一样,或者变量名中包含空格时,必须将变量名包含在“”中.例如:“SECTION”=9;“withaspace”=“alsowithaspace”+10;在arm-elf-ld命令语言中,空格用于界定相邻符号,例如:A-B表示一个变量名,而A-B表示一个减法的表达式。第48页/共202页③地址记数器点号“.”“.”是一个包含当前输出地址的计数器。因为“.”总是表示某个输出段的地址,所以总是和表达式一起在SECTIONS命令中出现。“.”可以在任何一般符号出现的地方出现,对“.”的赋值将引起计数器所指位置的移动,而计数器位置不能反向移动。第49页/共202页例如:SECTIONS { output:
{ file1(.text) .=.+1000;
file2(.text) .+=1000;
file3(.text) }=0x1234;
}在左面的例子中,在file1(.text)与file2(.text)之间被空出了1000个字节的空间,file2(.text)与file3(.text)之间也被空出了1000个字节的空间,而0x1234为该分段的空间空隙的填充值。第50页/共202页可以将“.”赋给变量;也可以对“.”赋值。例如:
data_start=.;
.=.+2000;第51页/共202页(3)linkcmds的结构linkcmds文件主要由四个部分组成:程序入口说明:用于指定程序运行时所需要执行的第一条指令的地址。程序头说明:生成目标文件类型为ELF,可以指定详细的程序头信息。内存布局的说明:用于规划内存的布局,将内存空间划分为不同的部分。分段的分步说明:详细指明各个分段的构成以及分段的定位地址和装载地址。
其中①和④的部分不能被省略。第52页/共202页(4)对程序入口的说明arm-elf-ld命令语言有一条特定命令用于指定输出文件中第一条可执行指令,即程序的入口点。该命令格式如下:
ENTRY(symbol)其中ENTRY是保留字,symbol表示程序的入口地址,通常是用一个全局地址标号(label)来表示入口地址。例如,在程序中的开始地方有一标号:.globaldemo_startdemo_start:movl$_stack_top,%esp……第53页/共202页那么在linkcmds中可以用下面的方式说明程序的入口:ENTRY(demo_start);该命令可以作为单独的一条命令放在linkc–mds的任何位置,也可以放在SECTIONS内关于段的定义部分,都对布局起作用。指定入口地址的方式还有很多,现在按优先级递减的顺序描述如下:用‘-e’选项指定入口地址在linkcmds里用ENTRY(symbol)指令变量start的值,如果有变量start.text段第一字节的地址,如果存在0地址第54页/共202页(5)对程序头的说明ELF格式文件需要使用程序头,它用于描述程序应该怎么被装入内存。在默认情况下,arm-elf-ld可以自己生成一个程序头,用户也可以用PHDRS自己编写程序头,当运用该命令时,arm-elf-ld不会生成默认的程序头。注意:如果没有特殊要求,建议用户不要自己写程序头。第55页/共202页PHDRS{nametype[FILEHDR][PHDRS][AT(address)] [FLAGS(flags)];}其中PHDRS、FILEHDR、AT、FLAGS都是关键字。name表示段(Segment)的名字,而该段(Segment)装入的内容由SECTIONS中对分段(Section)的描述决定,例如:SECTIONS{…secnamestartBLOCK(align)(NOLOAD):AT(ldadr){contents}>region:phdr=fill…}第56页/共202页因此PHDRS中的name应该和SECTIONS中的phdr保持一致。type表示段的类型,可以为下面描述的任意一种类型(括号内表示关键字的值):PT_NULL(0)——空程序头PT_LOAD(1)——描述一个可装入的段PT_DYNAMIC(2)——表示包含动态链接信息的段PT_INTERP(3)——表示该段包含程序解释器的名字PT_NOTE(4)——表示包含注释信息的段PT_SHLIB(5)——一个保留的程序头PT_PHDR(6)——表示该段可能包含程序头的描述信息expression——用数值表示一个程序头的类型,该类型没有对应的关键字第57页/共202页FILEHDR表示在段中包含ELF文件头的信息。PHDRS表示在段中还要包含程序头本身的信息。[AT(address)]表示该段的起始地址,若在SECTIONS中也有AT时,程序头中定义的AT优先。例如:
PHDRS { headersPT_PHDRPHDRS; interpPT_INTERP; textPT_LOADFILEHDRPHDRS; dataPT_LOAD; dynamicPT_DYNAMIC; }第58页/共202页SECTIONS{.=SIZEOF_HEADERS;.interp:{*(.interp)}:text:interp.text:{*(.text)}:text.rodata:{*(.rodata)}/*defaultsto:text*/....=.+0x1000;/*movetoanewpageinmemory*/.data:{*(.data)}:data.dynamic:{*(.dynamic)}:data:dynamic...}第59页/共202页在上面的例子中,定义了5个段:headers申明一个程序头段;interp申明一个段,段中包含了程序解释器的名字;text申明一个可被下载的段,并且包含了文件的头信息和各段的信息;data申明一个可被下载的段;dynamic申明一个包含动态链接信息的段;第60页/共202页在SECTIONS中可以看到,有的分段同时属于两个段,实质上是这两个段占用同一空间。.rodata也属于.text段是由于它的上一个分段属于.text段,而.rodata又没有指明归属段。注意:如果没有特殊要求,建议用户不要自己写程序头。第61页/共202页(6)对内存布局的说明arm-elf-ld的默认配置允许将输出程序定位到任何可用内存。用户也可以用MEMORY命令对内存进行配置。MEMORY命令可以定义目标机内存段的位置和大小,当装载的程序块大小超出指定的内存段大小时,arm-elf-ld会提示出错,而不会自动寻找可用的内存段,这样可以避免内存分配错误。第62页/共202页定义内存段的方式:MEMORY {name(attr):ORIGIN=origin,LENGTH=len…}name表示内存段的名字,可以使用任何变量名,但是不能和已有变量名、文件名和分段名(sectionname)冲突。attr没有实际的用途,可省略。origin(可简写为:org或者o)表示内存段的起始位置。Length(可简写为:len或者l)表示内存段的长度.第63页/共202页MEMORY{rom:ORIGIN=0x3f80000,LENGTH=512Kram:org=0,l=1M}
表示定义了两个内存段:rom内存段,起始地址为0x3f80000,长度为512K;ram内存段,起始地址为0,长度为1M。第64页/共202页(7)对分段的说明SECTIONS命令控制如何正确地将输入分段定位到输出分段,包括在输出文件中的顺序,和输入分段在输出分段中的定位。如果不用SECTIONS命令,arm-elf-ld将对每个输入分段生成相同名字的输出分段,分段的顺序由输入文件中遇到的分段的先后顺序决定。第65页/共202页SECTIONS命令的格式:SECTIONS{...secnamestartBLOCK(align)(NOLOAD):AT(ldadr){contents}>region:phdr=fill...}其中secname和contents都是必须有的。secname表示输出分段的名字,受输出格式的限制,一些输出格式对段名有限制,例如a.out只允许.text,.data或.bss的分段名存在.另外arm-elf-ld不输出空的分段。
第66页/共202页start,BLOCK(align),(NOLOAD),AT(ldadr),>region,:phdr,=fill都是可选项:Start
表示分段的起始地址,该地址被称为重定位地址;BLOCK(align)表示分段以align对齐;(NOLOAD)表示该段不能被装载;AT(ldadr)
表示该分段装入的起始地址为ldadr,当没有该参数时分段的装入地址和重定位地址相同;第67页/共202页region
表示该分段地址空间在region所定义的范围内,region就是在MEMORY命令中定义的内存段名字;:phdr
表示该分段的装载地址空间在phdr定义的范围内,phdr就是在程序头中定义的段名字;=fill
表示在该分段的空间空隙的填充值。第68页/共202页contents表示具体的分段内容,主要描述该输出分段中包含有输入文件中的哪些分段。常见的分段名如下:.text ——表示代码段.data ——初始化了的数据段.bss ——未初始化的数据段.rodata ——不可写的数据段COMMON ——未初始化的数据段第69页/共202页用户在汇编语言程序中可以自定义分段名,如:mycode、mydata之类。在C语言文件编译成目标文件后,通常包含有.text、.data、COMMON、.rodata段。其中.rodata表示不可写的数据段,通常包含在C语言程序中定义的一些常量,如constcharversion_string[]=“Lambdax86/fpm”之类。第70页/共202页contents可用格式:filenamefilename(section)filename(section,section,…)filename(sectionsection…)和针对所有文件的:*(section)*(section,section,…)*(sectionsection…)第71页/共202页
如果在用“*”指定所有文件时,以前已经使用filename指定过一些文件,那么“*”表示剩下的文件:
filename(COMMON) *(COMMON) 指定输入文件中名为COMMON的分段里未初始化的数据在输出分段中的位置。 下面举例说明contents中的具体内容及编写方法。第72页/共202页下面举例说明contents中的具体内容及编写方法。例如:
.text0: {file1.ofile2.ofile3.o}
表示将file1.o、file2.o、file3.o中的所有分段都放在输出文件的.text段中。例如:
.text0: { *(.text); }
表示将所有输入文件中的.text分段都放在输出文件的.text段中。第73页/共202页例如:
.text0: { file1.o(.text); file2.o(.text); file3.o(.text); }
表示将file1.o、file2.o、file3.o中的.text段都放在输出文件的.text段中。第74页/共202页例如:text1: { file1.o(.text); }text2: { *(.text); }
表示将file1.o中的.text段放在输出文件的text1段中,而其他输入文件的.text段都放在输出文件的text2段。第75页/共202页(8)注释 arm-elf-ld语言中的注释和C语言一样。
例如:/*comments*/第76页/共202页3.4工程管理器MAKE3.4.1概述make是用于自动编译、链接程序的实用工具。使用make后就不需要手工编译每个程序文件。第77页/共202页要使用make,首先要编写makefile,makefile描述程序文件之间的依赖关系以及提供更新文件的命令。典型地,在一个程序中,可执行文件依赖于目标文件,而目标文件依赖于源文件。
如果makefile文件存在,每次修改完源程序后,用户通常所需要做的事情就是在命令行敲入“make”,然后所有的事情都由make来完成。
第78页/共202页1.命令格式make[-fmakefile][option][target]…
make命令后跟-f选项,指定makefile的名字为makefile;option表示make的一些选项;target是make指定的目标,在3.4.3将详细说明。例如:makefile的名字是my_hello_make:
make–fmy_hello_make第79页/共202页2.命令选项列表-f 指定makefile-e 使环境变量优先于makefile的变量-Idir 设定搜索目录-i 忽略make过程中所有错误-n 只显示执行过程,而不真正执行-r 使隐含规则无效-w 显示工作目录-Cdir 读取makefile设置的工作目录-s 不显示执行的命令第80页/共202页3.4.2
命令使用
makefile文件用来告诉make需要做的事情,通常指怎样编译、怎样链接一个程序。以C语言程序为例:在用make重新编译的时候,如果一个头文件已被修改,则包含这个头文件的所有C源代码文件都必须被重新编译。而每个目标文件都与C的源代码文件有关,如果有源代码文件被修改过,则所有目标文件都必须被重新链接生成最后的结果。编写一个makefile将在3.4.3节详细介绍。第81页/共202页1.指定makefile-fmakefile用该选项指定makefile的名字为makefile。如果make中多次使用-f指定多个makefile,则所有makefile将链接起来作为最后的makefile。如果不指定makefile,make默认的makefile依次为“makefile”、“Makefile”。例如:make–fmy_hello_make第82页/共202页2.使环境变量优先于makefile文件中的变量-e使环境变量优先于makefile文件中的变量。例如:
make–e第83页/共202页3.指定包含文件的搜索路径-Idir指定在解析makefile文件中的.include时的搜索路径为dir。如果有多个路径,将按输入顺序依次查找。例如:make–I/include/mk第84页/共202页4.忽略错误-i忽略make执行过程中的所有错误。例如:
make–i5.显示命令的执行过程-n只显示命令的执行过程而不真正执行。例如:
make–n第85页/共202页6.使隐含规则无效-r使make的隐含规则无效,清除后缀名规则中默认的后缀清单。例如:
make–r7.显示执行过程中的工作目录-w显示make执行过程中的工作目录。例如:
make–w第86页/共202页8.读取makefile文件前设置工作目录-Cdir在读取makefile文件以前将工作目录改变为dir,完成make后改回原来的目录。如果在一次make中使用多个-C选项,每个选项都和前面一个有关系。“-Cdir0/-Cdir1”与“-Cdir0/dir1”等价.例如:
make–Cbsp第87页/共202页9.不显示所执行的命令-s运行make时用选项-s可以不显示执行的命令,只显示生成的结果文件。例如:
make–s第88页/共202页3.4.3编写一个makefile1.makefile的结构makefile文件包含:显式规则隐含规则变量定义指令注释第89页/共202页2.编写makefile中的规则makefile中规则的格式如下:
targets:dependencies command …
或者
targets:dependencies;command command …targets
指定目标名,通常是一个程序产生的目标文件名,也可能是执行一个动作的名字,名字之间用空格隔开。dependency
描述产生target所需的文件,一个target通常依赖于多个mand
用于指定该规则的命令。注意:command必须以TAB键开头。如果某一行过长可以分作两行,用‘\’连接。第90页/共202页例如:smcinit:smc.oconfig.oarm-elf-ar–ruvs–osmcinit.asmc.oconfig.osmc.o:smc.cinclude.harm-elf-gcc–c–osmc.osmc.cconfig.o:config.cinclude.harm-elf-gcc–c–oconfig.oconfig.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–osmcinit.asmc.oconfig.o;arm-elf-gcc–c–osmc.osmc.c;arm-elf-gcc–c–oconfig.oconfig.c来生成。clean为一动作名,删除所有后缀为.o的文件。第91页/共202页3.make调用makefile中的规则在默认情况下,make运行不是以“.”开头的第一条规则。在上面的例子中,make默认执行的是规则smcinit,此时只需要输入命令:makemake将读入makefile,然后执行第一条规则,例子中该规则是链接目标文件生成库,因此必须执行规则smcinit依赖的规则smc.o和config.o。在执行过程中将自动更新他们所依赖的文件。有些规则不是被依赖的规则,需要make指定才能被运行,如上面的例子中的clean规则可以这样执行:makeclean这两种方式的结果一样。只是第一种方式没指明目标名,第二种方式指明了目标名。第92页/共202页4.设置makefile中文件的搜索路径在makefile中,可以通过给VPATH赋值来设置规则中目标文件和依赖文件的搜索目录。make首先搜索当前目录,如果未找到依赖的文件,make将按照VPATH中给的目录依次搜索。VPATH对makefile中所有文件都有效。例如:demo.o:demo.cdemo.hdemo.c在目录//c/demo/中,demo.h在目录//c/demo/head/中,则可以给VPATH变量赋值:VPATH:=//c/demo//c/demo/head或者VPATH:=//c/demo://c/demo/head也可以使用指令vpath,与VAPTH在使用上的区别是:vpath可以给不同类文件指定不同的搜索目录。%.o表示所有以.o结尾的子串。第93页/共202页vpath%.c//c/demovpath%.h//c/demo/headvpath%.c——表示清除所有vpath对%.c设置的搜索目录vpath——表示清除所有以前用vpath设置的搜索目录这两种方式的效果是一样的,但是后一种要明确一些。这样make就会根据VPATH或者vpath来搜索相应的依赖文件。第94页/共202页5.如何定义变量为了简化makefile以及减少不必要的错误,可以用变量的形式来代表目标文件名或字符串,在需要使用时直接调用变量。在makefile中变量可以被这样定义:
CC=arm-elf-gcc AS:=arm-elf-as AR=arm-elf-ar LIBPATH:=./lib第95页/共202页从上面的定义中可以看出,有两种定义变量的形式:变量名=值变量名:=值两者的不同点在于,前者定义的变量是在被用到时才取它的值,而后者则是在定义变量或者给它赋值时就确定了它的值。第96页/共202页例如:
var1=hellofirst var2=${var1} var1=hellosecond test_echo:
echo${var2}执行的结果是显示:hellosecond var1=hellofirst var2:=${var1} var1=hellosecond test_echo:
echo${var2}执行的结果是显示:hellofirst第97页/共202页例如:var1=hellofirstvar1=${var1}andsecondecho_test:echo${var1}会陷入死循环中。var1:=hellofirstvar1:=${var1}andsecondecho_test:echo${var1}会显示:hellofirstandsecond第98页/共202页6.引用变量有两种方式:${VarName}$(VarName)
两种方式的效果一样。VarName表示变量名。第99页/共202页7.make提供的常用变量$@——表示目标名$^——表示所有的依赖文件$<——第一个依赖文件例如:demo.o:demo.cdemo.h${CC}${CFLAGS}$<-o$@$<的值为demo.c,$@的值为demo.o,而$^的值为demo.cdemo.h。第100页/共202页8.make里的常用函数函数的使用方式有两种:$(functionarguments)${functionarguments}常用的函数有:(1)$(substfrom,to,text)将字text中的from子串替换为to子串。例如:STR:=$(substIam,Heis,Iamanengneer)与STR:=Heisanengneer相同。第101页/共202页(2)$(patsubstpattern,replacement,text)按模式pattern替换text中的字串。例如:
OBJS=init.omain.ostring.o STR:=$(patsubst%.o,%.c,${OBJS}) STR的值为:init.cmain.cstring.c%.o表示所有以.o结尾的子串。$(wildcardpattern...)表示与pattern相匹配的所有文件。例如:在当前目录中有文件init.c、main.c和string.c:
SRCS:=$(wildcard*.c)则SRCS的值为init.cmain.cstring.c第102页/共202页9.隐含规则隐含规则是指由make自定义的规则,常用的有:由*.c的文件生成*.o的文件由*.s的文件生成*.o的文件 例如,下面是某makefile的一部分:
CC=arm-elf-gcc AS=arm-elf-as LD=arm-elf-ld CFLAGS=-c-ansi-nostdinc-I--I./ ASFLAGS= LDFLAGS=-Mapmap.txt-N-Tlinkcmds-L./lib第103页/共202页 OBJS=i386ex-start.oi386ex-get-put-char.oi386ex-io.o OBJCOPY=arm-elf-objcopy OBJCOPYFLAG=-Oihex All:monitor.elf ${OBJCOPY}${OBJCOPYFLAG}monitor.elfmonitor.hex monitor.elf:${OBJS} ${LD}${LDFLAGS}-omonitor.elf${OBJS}-lmonitor clean:
rm-rf*.o*.elf
在该makefile中的i386ex-start.o、i386ex-get-put-char.o、i386ex-io.o都是由隐含规则生成的。第104页/共202页实际上使用的隐含规则如下所示:对*.c-->*.o的隐含规则为:%.o:%.c${CC}${CFLAGS}$<-o$@对于*.s-->*.o的隐含规则为:%.o:%.s${AS}${ASFLAGS}$<-o$@第105页/共202页3.5交叉汇编器arm-elf-as3.5.1概述arm-elf-as将汇编语言程序转换为ELF(ExecutableandLinkingFormat执行时链接文件格式)格式的可重定位目标代码,这些目标代码同其它目标模块或库易于定位和链接。arm-elf-as产生一个交叉参考表和一个标准的符号表,产生的代码和数据能够放在多个段(Section)中。第106页/共202页1.命令格式arm-elf-as[option…][asmfile…]在命令arm-elf-as后面跟一个或多个选项,以及该选项的子选项,选项间用空格隔开,然后跟汇编源文件名。例如,将demo.s编译成目标文件,并且设置头文件的搜索目录为C:\demo\include:arm-elf-as–I//c/demo/includedemo.s第107页/共202页2.命令选项列表-a[dhlns] 显示arm-elf-as信息-f 不进行预处理-Ipath 设置头文件搜索路径-o 设定输出文件名-v 显示版本信息-W 不显示警告提示-Z 不显示错误提示第108页/共202页3.5.2命令使用1.生成目标文件每次运行arm-elf-as只输出一个目标文件,默认状态下名字为a.out。可以通过-o选项指定输出文件名字,通常都以.o为后缀。例如:编译demo.s输出目标文件demo.o:
arm-elf-as–odemo.odemo.s第109页/共202页2.设置头文件搜索路径-Ipath添加路径path到arm-elf-as的搜索路径,搜索.include”file”指示的文件。-I可以被使用多次以添加多个目录,当前工作目录将最先被搜索,然后从左到右依次搜索-I指定的目录。例如:编译demo.s时指定两个搜索目录,当前目录和C:\demo\include:arm-elf-as–I../–I//c/demo/includedemo.s第110页/共202页3.显示arm-elf-as信息内容-a[dhlns]打开arm-elf-as信息显示。dhlns为其子选项,分别表示:d ——不显示调试信息h ——显示源码信息l ——显示汇编列表n ——不进行格式处理s ——显示符号列表第111页/共202页在不添加子选项时,-a表示显示源码信息,显示汇编列表,显示符号列表。添加子选项时将选项直接加在-a以后可以添加一个或多个。缺省时显示的信息输出到屏幕,也可用重定向输出到文件。例如:编译demo.s生成不进行格式处理的汇编列表,输出到文件a.txt:arm-elf-as–aln–odemo.odemo.s>a.txt第112页/共202页4.设置目标文件名字-ofilename每次运行arm-elf-as只输出一个目标文件,默认输出文件为a.out。可以通过-o选项指定输出文件名字,通常都以.o为后缀。如果指定输出文件的名字和现有某个文件重名,生成的文件将直接覆盖已有的文件。例如:编译demo.s输出目标文件demo.o:arm-elf-as–I/include–odemo.odemo.s第113页/共202页5.如何取消警告信息-W加选项-W以后,运行arm-elf-as就不输出警告信息。例如:编译demo.s输出目标文件demo.o,不输出警告信息:arm-elf-as–W–odemo.odemo.s第114页/共202页6.设置是否进行预处理arm-elf-as内部的预处理程序,完成以下工作:调整并删除多余空格,删除注释,将字符常量改成对应的数值。arm-elf-as不执行arm-elf-gcc预处理程序能完成的部分,如宏预处理和包含文件预处理。可以通过.include“file”对指定文件进行预处理。arm-elf-gcc可以对后缀为.S汇编程序进行其他形式的预处理。第115页/共202页如果源文件第一行是#NO_APP或者编译时使用选项-f将不进行预处理。如果要保留空格或注释,可以在需要保留部分开始加入#APP,结束的地方加#NO_APP。例如:编译demo.s输出目标文件demo.o,并且编译时不进行预处理,则命令如下:arm-elf-as–f–odemo.odemo.s第116页/共202页3.6汇编语言编程在ARM汇编语言程序里,有一些特殊指令助记符,这些助记符与指令系统的助记符不同,没有相对应的操作码,通常称这些特殊指令助记符为伪指令,它们所完成的操作称为伪操作。伪指令在源程序中的作用是为完成汇编程序作各种准备工作的,这些伪指令仅在汇编过程中起作用,一旦汇编结束,伪指令的使命就完成了。在ARM的汇编程序中,有如下几种伪指令:符号定义伪指令、数据定义伪指令、汇编控制伪指令、宏指令以及其他伪指令。第117页/共202页3.6.1汇编语言1.基本元素(1)字符集 汇编中使用下列字符组成源程序的各种语法元素:大写字母A~Z;小写字母a~z;数字0~9;符号+-*/=[]();,.:‘@$<>{}%_“\-|^?!。其中大小写字母作用不同。第118页/共202页(2)约定的名字包括寄存器名、指令名字和伪操作符。每一个伪操作符表示一定功能的操作。伪操作的功能由汇编系统实现,没有目标代码对应。这一点是伪操作符与操作符的不同之处。伪操作符是由汇编系统约定的名字,不用定义就能实现。第119页/共202页
伪操作符可以分为六类:数据定义伪操作符符号定义伪操作符程序结构伪操作符条件汇编伪操作符宏伪操作符其他伪操作符第120页/共202页(3)定义的名字汇编程序中的标号、分段名、宏定义名都是用户可以定义的名字。
①标号标号只能由a~z、A~Z、0~9、.、_等字符组成,标号的长度不受限制,大小写字母有区别。第121页/共202页当标号为0~9的单个数字时表示该标号为局部标号,局部标号可以多次重复出现。在引用时,使用方法如下(N代表0~9的数字):
Nf——在引用处的地方向前(程序地址增长的方向)的N标号。
Nb——在引用处的地方向后(程序地址增长的方向)的N标号。 标号在最终的绝对定位的代码中表示所在处的地址,因此在汇编中的标号可以在C/C++程序中当作变量或者函数来使用。第122页/共202页②分段名
汇编系统中预定义的分段名有:.text.bss.data.sdata.sbss等,但是用户可以自己定义段名,语法如下:
.sectionsection_nameattribute
例如:定义一个可以执行的代码段.mytext .section".mytext","ax" mycode …第123页/共202页③宏定义名宏定义的语法如下:.macromacro_nameparm1…parmNmacrobody.endm第124页/共202页(4)常数二进制数由0b或者0B开头,如:0b1000101、0B1001110;十六进制数以0x或者0X开头,如:0x4567、0X10089;八进制数由0开头,如:0345、09870;十进制数以非零数开头,如:345、12980例如:.byte74,0112,092,0x4A,0X4a,'J,'\J
.ascii"Ringthebell\7"第125页/共202页(5)当前地址数
当前的地址数用点号“.”表示,在汇编程序中可以直接使用该符号。第126页/共202页(6)表达式在汇编程序中可以使用表达式,在表达式中可以使用常数和数值。可以使用的运算符有: ①前缀运算符号
-——取负数
~——取补数 ②中缀运算符号 */%<<<>>>|&^!+-第127页/共202页(7)注释符号不同芯片的汇编程序中,注释的符号有所不同,ARM以“@”开头的程序行是注释行。第128页/共202页2.语句(1)语句类型汇编语句按其作用和编译的情况分为两大类:执行性语句和说明性语句。执行性语句是在编译后有目标程序与之对应,按其编译后目标程序的对应情况又可以分为:一般执行性语句和宏语句。一般执行性语句与目标程序是一一对应的,即一个一般执行语句只产生一条目标代码指令。宏语句由伪操作符定义,包括宏定义、宏调用及宏扩展语句。一个宏语句对应了一组目标代码程序,可以看成是一般执行性语句的扩展。第129页/共202页说明性语句由伪操作符定义,它用于用户以源程序方式和汇编程序通信。用户使用说明性语句表示源程序的终止说明、分段定义、数据定义、内存结构等信息。数据定义语句用于描述数据和给数据赋初值.列表控制语句用于说明源程序的格式要求。程序结构语句用于说明源程序的结构和目标程序的结构。条件汇编语句用于说明汇编某部分语句时的条件,满足条件则编译,否则跳过这部分不予编译.第130页/共202页(2)数据语句一字节数据定义语句语法:.byteexpressions例子:.byte0x89,0x45,56,‘K,‘M,023,0B101011两字节数据定义语句语法:.shortexpressions例子:.short0x6789,0b101110111四字节数据定义语句语法:.longexpressions例子:.long0x78896676,02356243563456八字节数据定义语法:.quadexpressions例子:.quad0x1122334455667788第131页/共202页单个字串定义语法:.string“string”例子:.string“thisisanexample”多个字串1语
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 承包个人机井合同(2篇)
- 二零二五年度牛羊肉线上线下融合营销合同3篇
- 二零二五年度光伏产品模具研发制造合同4篇
- 2025年度宠物用品跨境电商合作合同4篇
- 2025年度环保工程派遣员工劳动合同样本4篇
- 2025版绵阳市医疗机构租赁合同4篇
- 2025年度城市综合体施工合同(含装修工程)2篇
- 2025年美团外卖骑手服务区域划分合同
- 2025年冷链物流送货员专业培训及聘用合同
- 二零二五年度农业产业链借贷合同协议
- 湖北省五市州2023-2024学年高一下学期期末联考数学试题
- 城市作战案例研究报告
- 全册(教案)外研版(一起)英语四年级下册
- 【正版授权】 ISO 12803:1997 EN Representative sampling of plutonium nitrate solutions for determination of plutonium concentration
- 道德经全文及注释
- 2024中考考前地理冲刺卷及答案(含答题卡)
- 多子女赡养老人协议书范文
- 安踏运动品牌营销策略研究
- 彩票市场销售计划书
- 骨科抗菌药物应用分析报告
- 支付行业反洗钱与反恐怖融资
评论
0/150
提交评论