ADS/SDT IDE开发环境:它由ARM公司开发,使用了CodeWarrior公司的编译器
一般的:集成了GNU开发工具的IDE开发环境:它由GNU的汇编器as、交叉编译器gcc、和链接器ld等组成
常用伪操作可分为:
定义全局变量
语法格式 | 作用 |
---|---|
A | GBLA Variable |
L | GBLL Variable |
GBLS Variable | 声明一个全局字符串变量,初始化为空串 |
定义局部变量
语法格式 | 作用 |
---|---|
A | LCLA Variable |
L | LCLL Variable |
LCLS Variable | 声明一个局部字符串变量,初始化为空串 |
为变量赋值
语法格式 | 作用 |
---|---|
A | Variable SETA expr |
L | Variable SETL expr |
Variable SETS expr | 给一个字符串赋值 |
给一串寄存器命名
语法格式 | 作用 |
---|---|
T | name RLIST {list of registers} |
语法格式 | 作用 |
---|---|
{label} DCB expr | 分配一段字节 的内存单元,用字节的方式放expr |
{label} DCD expr | 分配一段字 的内存单元,用字的方式放expr |
语法格式 | 作用 |
---|---|
G | LTORG |
IF 逻辑表达式
{
ELSE
}
ENDIF
WHILE 逻辑表达式
...
WEND
MACRO
{$label} macroname {$parameter}
MEND
语法格式 | 作用 |
---|---|
16 | CODE 16 |
32 | CODE 32 |
语法格式 | 作用 |
---|---|
ame EQU expr | 将name赋值为expr |
语法格式 | 作用 |
---|---|
AREA sectioname {, attr} | 定义一个代码段或数据段 |
ENTRY | 指定程序的入口点 |
END | 告诉编译器已经到了源程序结尾 |
语法格式 | 作用 |
---|---|
T/GLOBAL | EXPORT symbol {[WEAK]} |
T/EXTERN | IMPORT/EXTERN symbol {[WEAK]} |
常用伪操作为:
常量编译控制伪操作
伪操作 | 语法格式 | 作用 |
---|---|---|
byte | .byte expr | 分配一段字节空间,并用字节的方式放入expr |
hword/ .short | .hword expr | 分配一段半字节空间,并用半字的方式放入expr |
ascii | .ascii expr | 定义字符串expr(非零结束符) |
asciz/.string | .asciz | 定义字符串(以 /0 为结束符) |
word | .word expr | 分配一段字内存空间 |
汇编程序代码控制伪操作
伪操作 | 语法格式 | 作用 |
---|---|---|
section | .section expr | 定义域中包含的段 |
text | .text{subsection} | 代码 |
data | .data {subsection} | 数据 |
code 16 | .code 16 | 表明后面是Thumb指令集 |
code 32 | .code 32 | 表明后面是ARM指令集 |
end | .end | 结束标识符 |
include | .include “filename” | 将一个源文件包含到当前源文件中 |
宏及条件编译控制伪操作
.macro以及.endm
.macro condition
.endm
.ifdef, .else及.endif
.ifdef condition
.else
.endif
其他伪操作
伪操作 | 语法格式 | 作用 |
---|---|---|
.print string | 打印信息到标准输出 |
伪操作 | 语法格式 | 作用 |
---|---|---|
ADR | ADR {cond} register, expr | 将基于PC或基址寄存器的地址读到寄存器中,小范围的地址读取 |
ADRL | ADRL {cond} register,expr | 将基于PC或基址寄存器的地址读到寄存器中,中等范围的地址读取 |
LDR | LDR {cond} register | 将一个32位的立即数或一个地址值读取到寄存器中,大范围地址读取 |
NOP | NOP | 汇编是替换成ARM的空指令(占用一个操作时间但什么到不做) |
文件格式
ARM源程序文件可以有任意一种纯文本
文件编写程序代码
文件格式对应与
程序文件 | 文件名 | 说明 |
---|---|---|
汇编程序文件 | *.S | 用ARM汇编语言编写的ARM程序或Thumb程序 |
C程序文件 | *.C | 用C语言编写的程序代码 |
头文件 | *.H | 通常将常量命名、宏定义、数据结构定义等放在头文件中 |
ARM汇编语言语句格式如下:
{符号} {指令 | 伪操作 | 伪指令} {; 注释}
;为注释符
符号可以代表地址、变量和数字常量
命名规则:符号由大小写字母、数字以及下划线组成(区分大小写)
局部标号以数字开头,其他符号都不能以数字开头
变量: 三种变量:数字变量、逻辑变量、串变量
数字常量:表示方式:十进制,十六进制,n进制
标号:表示程序中的指令或地址的标号,分为基于PC的标号、基于寄存器的标号、绝对地址
局部标号:相对当前位置
% {F|B} {A|T} N{routname}
其中:%表示引用操作、F表示只先向前搜索、B表示向后搜索、A表示编译器搜索宏的搜索嵌套层次、T表示宏的当前层次
LEN:返回字符串的长度
例:
GBLS STR
STR SETS "AAA"
:LEN: STR ;LEN = 3
CHR: 返回一个字符的ASCII值
:CHR:A
STR: 将对应变量(数字量或逻辑量)的表示形式用字符串的形式表示
例:
GLBA A1
SETA A1 15
:STR: A1
LEFT :返回一个字符从最左端的一定长度的字串
格式:
A :LEFT: B
A为源字符串;B为数字量,表示返回字符个数
例:
GBLS STR1
GBLS STR2
SETS STR1 "AAAABBBB"
SETS STR2 STR1 :LEFT:3 ;结果为STR2为 “AAA”
RIGHT同理,返回最右端一定长度的字串
CC:连接2个字符串
A :CC: B
A为第一个源字符串;B为第二个源字符串
例:
GBLS STR1
GBLS STR2
STR1 SETS "AAACCC"
STR2 SETS "BBB" :CC: (STR1 :LEFT: 3) ; 结果为STR2 为"BBBAAA"
:NOT: A
A + B ;
A - B;
A x B;
A / B;
A :MOD: B;
A :ROL: B ;将整数A循环左移B位
A :ROR: B;将整数A循环右移B位
A :SHL: B ;将整数A左移B位空位补0
A :SHR: B;将整数A右移B位空位补0
A :AND: B ;按位与操作
A :OR: B;按位或操作
A :EOR: B;按位异或操作
:LNOT: ;A 取反
A :LAND: B;逻辑与
A :LOR: B;逻辑或
A :LEOR: B;逻辑异或
ARM汇编语言是以段(section)为单位来组织源文件的。
段是相对独立的、具有特定名称的、不可分割的指令或者数据序列。
段又可以分为代码段和数据段。一个源程序至少需要一个代码段。
例:
AREA EXAMPLE(段的名字), CODE(代码段), READONLY(只读)
ENTRY(程序入口点)
start
...
END
子程序的调用
子程序的调用通过BL指令来完成
语法格式为
BL subname(被调用子程序的名称)
子程序的返回
在返回调用子程序时,将LR寄存器(R14)中的值拷贝回程序寄存器(R15)
当没有嵌套时
SUB2 ...
MOV PC, R14
当发生嵌套时, 对于在子程序中出现嵌套调用时,链接寄存器LR中的返回地址可能会在第二次调用时被覆盖,所以需要将返回地址压入堆栈来进行保存
SUB1 STMFD SP!, {R0 - R7, R14}; 保存工作寄存器和链接
BL SUB2
...
LDMFD SP!, {R0 - R7, PC}; 恢复工作寄存器并返回
跳转表
类似于c++中的switch
调用一系列子程序中的一个,而决定调用哪一个由程序的计算值决定。
例:
BL JUMPTAB; R0存放对应的跳转信息 0表示0号程序...
JUMPTAB ADR R1, SUBTAB; R1 <- SUBTAB
CMP R0, #SUBMAX; 检查是否超限
LDRLS PC, [R1, R0, LSL #2]; 如果OK则跳转到表中
B ERROR; 否则发生错误
SUBTAB DCD SUB0
DCD SUB1
DCD SUB2
...
SUB MAX;散转表结束地址
ARM与Thumb间的状态转换
状态切换是通过一条专用的转移交换指令BX来实现的。
当Rn寄存器中的目的地址的最后一位为0时转换到ARM状态
当Rn寄存器中最后一位为1时,转换到Thumb状态
Thumb地址是半字对齐的末尾一定是0
CODE32
ADR R0, Into_Thumb + 1
BX R0
...
CODE16
Into_Thumb:
...
ADR R5, BACK_TO_ARM
BX R5
...
CODE32
Back_to_ARM
...
应用实例:
变量定义
参数传递
为了单独编译C语言程序和汇编程序能够相互调用,定义了同一的函数过程调用标准ATPCS
ATPCS规则:
循环时使用i --
可以省一些汇编指令,更有效率
未完待续