目标:
学习掌握ARM公司开发工具支持的汇编程序设计语法,规则。
ARM汇编程序设计:
ARM汇编程序设计语法与汇编器有一定关系,不同的汇编工具语法会略有不同,比如ARM公司的开发工具和GNU的gcc for ARM汇编语法略有不同,但指令集方面还是一致的。
采用汇编语言编程缺点有:
1、 汇编语法不通用,代码移植性差
2、 编码效率低下
那为什么还需要汇编编程呢?
1、 有些功能只有使用汇编实现:比如关闭中断、开启中断、修改状体寄存器,部分CPU的初始化代码,异常处理程序等等
2、 可以使用汇编优化代码的效率,当然是你水平很高的情况下,否则你写代码不一定比编译器产生的代码效率高。
3、 掌握汇编编程对某些高级语言特性理解会更加深刻,比如大家都知道 C语言局部变量在栈上,如果没学过汇编也只能记住,反之如果学习了汇编的压栈,出栈指令,对栈进行过操作,使用栈传递过参数(数据)等,就会对局部变量在栈上理解更深刻。当然了不会汇编一样可以做软件开发。
ARM汇编编程语法:
1、 汇编语言编程,汇编源码文件通常以 .s或者 .asm结尾,ARM汇编以.s或者.S结尾。头文件一般以 .inc结尾,也可以.h结尾。
2、 汇编源文件和C语言类似,都是以行为单位,每行结构如下:
{;comment}
label:可选,标号,表示代码或者数据的起始位置,标号顶个写,前面不能有空格。
:可选,ARM指令、伪操作、伪指令三者中的一种,同时使用一种,三选一。
;comment:可选,注释。
代码示例如下:
其中:
1、 AREA、ENTRY、END属于ARM汇编伪操作。
2、 start,stop属于标号
3、 mov、add、b是ARM指令
4、 每行一条语句
5、 指令,伪指令,伪操作不能顶个写
6、 一行代码太长可以使用 \ 续行
7、 指令、伪指令、伪操作寄存器名可以大写,也可以小写,但不能大小写混写
ARM汇编标号命名:
标号分为全局标号和局部标号,局部标号只在某段范围内起作用。
1、 标号命名可以由字母、数字、下划线构成。
2、 除了局部标号外,不能由数字开头。
3、 区分大小写(大小写敏感)。
4、 除局部标号外,在其作用范围内,必须唯一。
ARM汇编寄存器命名:
ARM汇编伪操作:
ARM汇编工具支持的汇编伪操作包括符号定义伪操作、数据定义伪操作、汇编信息报告控制伪操作、汇编代码控制伪操作、文件包含伪操作、指令集类型标识伪操作以及其他功能伪操作等。
段定义伪操作:
段定义属性(attr):
段定义伪操作示例:
ARM指令集选择伪操作:
代码示例:
AREA Init,CODE,READONLY
……
CODE32 ;告诉编译器其后为32位的ARM指令
LDR R0,=NEXT+1 ;将跳转地址放入寄存器R0
BX R0 ;跳转并切换到Thumb工作状态
……
CODE16 ;告诉编译器其后为16位的Thumb指令
NEXT LDR R3,=0x3FF
……
END ;程序结束
END伪操作:
表示源文件结束,文件中END后面的内容不会被汇编器汇编。
ENTRY指定程序入口点伪操作:
通常用于指定程序入口起始地址,链接调试时会用到,不用ENTRY用其他方法也可以达到该效果。
全局标号声明伪操作:
示例:
AREA Init,CODE,READONLY
EXPORT Stest
Stest
MOV R0,R1
……
END
标号导出EXPORTAS伪指令:
标号导入/外部标号引用伪指令:
ARM变量定义伪操作:
ARM中变量是指其值在程序的运行过程中可以改变的量。ARM/Thumb汇编程序所支持的变量有三种。
变量赋值伪操作:
变量定义赋值代码示例:
GBLA TestA ;声明一个局部的数字变量 TestA
TestA SETA 0xaa ;将该变量赋值为0xaa
GBLL TestL ;声明一个局部的逻辑变量 TestL
TestL SETL ;将该变量赋值为真
GBLS TestS ;定义一个局部的字符串变量TestS
TestS SETS “Testing” ;将该变量赋值为"Testing"
GBLA objectsize
objectsize SETA oxff
SPACE objectsize
编译时的变量替换:
变量替换代码示例:
; straightforward substitution
GBLS add4ff
;
add4ff SETS "ADD r4,r4,#0xFF" ; set up add4ff
$add4ff.00 ; invoke add4ff
; this produces
ADD r4,r4,#0xFF00
; elaborate substitution
GBLS s1
GBLS s2
GBLS fixup
GBLA count
;
count SETA 14
s1 SETS "a$$b$count" ; s1 now has value a$b0000000E
s2 SETS "abc"
fixup SETS "|xy$s2.z|" ; fixup now has value |xyabcz|
|C$$code| MOV r4,#16 ; but the label here is C$$code
ARM中的常量:
代码示例:
Str DCB “This is a test!”;结尾没有NULL
C_string DCB "C_string",0
Num DCB 1,2,3,4,5
AREA Mydata, DATA,READWRITE
DCB 255 ;字节定义使内存单元不能字对齐
Data3 DCDU 1,5,20 ;
内建变量使用示例:
IF = "4T“
IF = 32
IF
IF
领取专属 10元无门槛券
私享最新 技术干货