第一部分 L i n u x下A R M汇编语法尽管在L i n u x下使用C或C++编写程序很方便,但汇编源程序用于系统最基本的初始化,如初始化堆栈指针、设置页表、操作 A R M的协处理器等。初始化完成后就可以跳转到C代码执行。需要注意的是,G N U的汇编器遵循A T&T的汇编语法,可以从G N U的站点 (w w w.g n u.o r g)上下载有关规范。
一.L i n u x汇编行结构
任何汇编行都是如下结构:
[:][}@c o m m e n t
[:][}@注释
L i n u x A R M汇编中,任何以冒号结尾的标识符都被认为是一个标号,而不一定非要在一行的开始。
【例1】定义一个"a d d"的函数,返回两个参数的和。
.s e c t i o n.t e x t,“x”
.g l o b a l a d d@g i v e t h e s y m b o l a d d e x t e r n a l l i n k a g e
a d d:
A D D r0,r0,r1@a d d i n p u t a r g u m e n t s
M O V p c,l r@r e t u r n f r o m s u b r o u t i n e
@e n d o f p r o g r a m
二.L i n u x汇编程序中的标号
标号只能由a~z,A~Z,0~9,“.”,_等字符组成。当标号为0~9的数字时为局部标号,局部标号可以重复出现,使用方法如下:
?标号f:在引用的地方向前的标号
?标号b:在引用的地方向后的标号
【例2】使用局部符号的例子,一段循环程序
1:
s u b s r0,r0,#1@每次循环使r0=r0-1
b n e1f@跳转到1标号去执行
局部标号代表它所在的地址,因此也可以当作变量或者函数来使用。
三.L i n u x汇编程序中的分段
(1).s e c t i o n伪操作
用户可以通过.s e c t i o n伪操作来自定义一个段,格式如下:
.s e c t i o n s e c t i o n_n a m e[,"f l a g s"[,%t y p e[,f l a g_s p e c i f i c_a r g u m e n t s]]]
每一个段以段名为开始,以下一个段名或者文件结尾为结束。这些段都有缺省的标志(f l a g s),连接器可以识别这些标志。(与a r m a s m中的A R E A相同)。
下面是E L F格式允许的段标志
含义
a允许段linux字符串转数组
w可写段
x执行段
【例3】定义段
.s e c t i o n.m y s e c t i o n@自定义数据段,段名为 “.m y s e c t i o n”
.a l i g n2
s t r t e m p:
.a s c i i"T e m p s t r i n g\n\0"
(2)汇编系统预定义的段名
.t e x t@代码段
.d a t a@初始化数据段
.b s s@未初始化数据段
.s d a t a@
.
s b s s@
需要注意的是,源程序中.b s s段应该在.t e x t之前。
四.定义入口点
汇编程序的缺省入口是 s t a r t标号,用户也可以在连接脚本文件中用E N T R Y标志指明其它入口点。
【例4】定义入口点
.s e c t i o n.d a t a
.s e c t i o n.b s s
.s e c t i o n.t e x t
.g l o b l_s t a r t
_s t a r t:
五.L i n u x汇编程序中的宏定义
格式如下:
.m a c r o宏名 参数名列表 @伪指令.m a c r o定义一个宏
宏体
.e n d m@.e n d m表示宏结束
如果宏使用参数,那么在宏体中使用该参数时添加前缀“\”。宏定义时的参数还可以使用默认值。
可以使用.e x i t m伪指令来退出宏。
【例5】宏定义
.m a c r o S H I F T L E F T a,b
.i f\b”表示不相等,其他的符号如:+、-、*、/、%、、>>、|、&、^、!、==、>=、 {,}分配n u m b e r_o f_b y t e s字节的数据空间,并填充其值为f i l l_b y t e,若未指定该值,缺省填充0。(与a r m a s m中的S P A C E功能相同)
(10).w o r d{,}…
插入一个32-b i t的数据队列。(与a r m a s m中的D C D功能相同)
可以使用.w o r d把标识符作为常量使用
例如:
S t a r t:
v a l u e O f S t a r t:
.w o r d S t a r t
这样程序的开头S t a r t便被存入了内存变量v a l u e O f S t a r t中。
(11).h w o r d{,}…
插入一个16-b i t的数据队列。(与a r m a s m中的D C W相同)
八.G N U A R M汇编特殊字符和语法
代码行中的注释符号:‘@’
整行注释符号:‘#’
语句分离符号:‘;’
直接操作数前缀:‘#’ 或 ‘$’
第二部分 G N U的编译器和调试工具
一.编译工具
1.编辑工具介绍
G N U提供的编译工具包括汇编器a s、C编译器g c c、C++编译器g++、连接器l d和二进制转换工具o b j c o p y。基于A R M平台的工具分别为a r m-l i n u x-a s、a r m-l i n u x-g c c、a r m-l i n u x-g++、a r m-l i n u x-l d和a r m-l i n u x-o b j c o p y。G N U的编译器功能非常强大,共有上百个操作选项,这也是这类工具让初学者头痛的原因。不过,实际开发中只需要用到有限的几个,大部分可 以采用缺省选项。G N U工具的开发流程如下:编写C、C++语言或汇编源程序,用g c c或g++生成目标文件,编写连接脚本文件,用连接器生成最终目标文 件(e l f格式),用二进制转换工具生成可下载的二进制代码。
(1)编写C、C++语言或汇编源程序
通常汇编源程序用于系统最基本的初始 化,如初始化堆栈指针、设置页表、操作A R M 的协处理器等。初始化完成后就可以跳转到C代码执行。需要注意的是,G N U的汇编器遵循A T&T的汇 编语法,读者可以从G N U的站点(w w w.g n u.o r g)上下载有关规范。汇编程序的缺省入口是 s t a r t标号,用户也可以在连接脚本文件中用E N T R Y标志指明其它入口点(见下文关于连接脚本的说明)。
(2)用g c c或g++生成目标文件
如果应用程序包括多个文件,就需要进行分别编译,最后用连接器连接起来。如笔者的引导程序包括3个文件:i n i t.s(汇编代码、初始化硬件)x m r e c e v e r.c(通信模块,采用X m o d e协议)和f l a s h.c(F l a s h擦写模块)。
分 别用如下命令生成目标文件: a r m-l i n u x-g c c-c-O2-o i n i t.o i n i t.s a r m-l i n u x-g c c-c-O2-o x m r e c e v e r.o x m r e c e v e r.c a r m-l i n u x-g c c-c-O2-o f l a s h.o f l a s h.c其中-c命令表示只生成目标代码,不进行连接;-o命令指明目标文件的名称;-O2表示采用二级优化,采用优化后可使生成的代码更短,运行速度更快。如果 项目包含很多文件,则需要编写m a k e f i l e文件。关于m a k e f i l e的内容,请感兴趣的读者参考相关资料。
(3)编写连接脚本文件
g c c等编译器内置有缺省的连接脚本。如果采用缺省脚本,则生成的目标代码需要操作系统才能加载运行。为了能在嵌入式系统上直接运行,需要编写自己的连接脚本文 件。编写连接脚本,首先要对目标文件的格式有一定了解。G N U编译器生成的目标文件缺省为e l f格式。e l f文件由若干段(s e c t i o n)组成,如不特 殊指明,由C源程序生成的目标代码中包含如下段:.t e x t(正文段)包含程序的指令代码;.d a t a(数据段)包含固定的数据,如常量、字符 串;.b s s(未初始化数据段)包含未初始化的变量、数组等。C++源程序生成的目标代码中还包括.f i n i(析构函数代码)和.i n i t(构造函数代码)等。连接器的任务就是将多个
目标文件的.t e x t、.d a t a和.b s s等段连接在一起,而连接脚本文件是告诉连接器从什么地址 开始放置这些段。例如连接文件l i n k.l d s为:
E N T R Y(b e g i n)
S E C T I O N
{
.=0x30000000;
.t e x t:{*(.t e x t)}
.d a t a:{*(.d a t a)}
.b s s:{*(.b s s)}
}
其 中,E N T R Y(b e g i n)指明程序的入口点为b e g i n标号;.=0x00300000指明目标代码的起始地址为0x30000000,这一段地址为 M X1的片内R A M;.t e x t:{*(.t e x t)}表示从0x30000000开始放置所有目标文件的代码段,随后的.d a t a:{*(.d a t a)}表示数据段从代码段的末尾开始,再后是.b s s段。
(4)用连接器生成最终目标文件
有了连接脚本文件,如下命令可生成最终的目标文件:
a r m-l i n u x-l d–n o s t a d l i b–o
b o o t s t r a p.e l f-T l i n k.l d s i n i t.o x m r e
c e v e r.o f l a s h.o
其中,o s t a d l i b表示不连接系统的运行库,而是直接从b e g i n入口;-o指明目标文件的名称;-T指
明采用的连接脚本文件(也可以使用-T t e x t a d d r e s s,a d d r e s s表示执行区地址);最后是需要连接的目标文件列表。
(5)生成二进制代码
连接生成的e l f文件还不能直接下载执行,通过o b j c o p y工具可生成最终的二进制文件:
a r m-l i n u x-o
b j
c o p y–O b i n a r y b o o t s t r a p.e l f b o o t s t r a p.b i n
其中-O b i n a r y指定生成为二进制格式文件。O b j c o p y还可以生成S格式的文件,只需将参数换成-O s r e c。还可以使用-S选项,移除所有的符号信息及重定位信息。如果想将生成的目标代码反汇编,还可以用o b j d u m p工具:
a r m-l i n u x-o
b j d u m p-D b o o t s t r a p.e l f
至此,所生成的目标文件就可以直接写入F l a s h中运行了。
2.M a k e f i l e实例
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论