第四章 ARM汇编语言程序设计
4.1 arm伪指令
包括6种伪指令:符号定义伪指令、数据定义伪指令、汇编控制伪指令、框架描述伪指令、信息报告伪指令、其他伪指令。
4.1.1 符号定义伪指令:用于定义arm汇编程序中的变量,对变量进行赋值以及定义寄存器名称。
GBLA、GBLL、GBLS 声明全局变量
LCLA、LCLL、LCLS 声明局部变量
SETA、SETL、SETS 给变量赋值
RLIST 寄存器列表定义名称
CN 协处理器的寄存器定义名称
CP 协处理器定义名称
DN、SN 为VFP(浮点体系结构)的寄存器定义名称
FN 为FPA的浮点寄存器定义名称
GBLA、GBLL、GBLS
GBLA 声明一个全局数字变量,并初始化为0
GBLL 声明一个全局逻辑变量,并初始化为{FALSE}
GBLS 声明一个全局字符串变量,并初始化为空串""
示例
GBLA objectsize ;声明一个全局的数字变量,初始化为0
objectsize SETA 0xFF ;将变量objectsize赋值为0xFF
SPACE objectsize ;引用该变量
GBLL statusB ;声明一个全局逻辑变量statusB
statusB SETL {TRUE} ;给逻辑变量statusB赋值为TRUE
LCLA、LCLL、LCLS
LCLA 声明一个局部数字变量,并初始化为0
LCLL 声明一个局部逻辑变量,并初始化为{FALSE}
LCLS 声明一个局部字符串变量,并初始化为空串
SETA、SETL、SETS
SETA 给数字变量赋值
SETL 给逻辑变量赋值
SETS 给字符串变量赋值
GBLS message ;定义一个全局串变量
message SETS ”hello!" ;给该串变量赋值
RLIST
RLIST 为一个通用寄存器列表定义名称
Context RLIST {R0-R6,R8,R10-R12,R15} ;将寄存器列表名称定义为Context
CN
CN 为一个协处理器的寄存器定义名称
power CN 6 ;将协处理的寄存器6名称定义为power
CP
CP 为一个协处理器定义名称
Dmu CP 6 ;将协处理器6名称定义为Dmu
DN、SN
DN 为一个双精度的VFP寄存器(编号0~15)定义名称
SN 为一个单精度的VFP寄存器(编号0~31)定义名称
height DN 6 ;将VFP双精度寄存器6名称定义为height
width SN 16 ; 将VFP单精度寄存器16名称定义为width
FN
FN 为一个FPA浮点寄存器(编号0~7)定义名称
fat FN 5 ;将浮点寄存器5名称定义为fat
4.1.2 数据定义伪指令
LTORG 声明一个数据缓冲池的开始
MAP 定义一个内存表的首地址
FIELD 定义内存表中的数据域
SPACE 分配一块内存单元,并用0初始化
DCB 分配一字节的内存单元
DCD及DCDU 分配一字的内存单元
DCDO 分配一字的内存单元,初始化为偏移量
DCFD及DCFDU 分配一双字的内存单元,并用双精度的浮点数据初始化
DCFS及DCFSU 分配一单字的内存单元,并用单精度的浮点数据初始化
DCI 分配一段字节的内存单元
DCQ及DCQU 分配一段双字的内存单元
DCW及DCWU 分配一段半字的内存单元
DATA 在代码段中使用数据,现已不再使用。
LTORG
LTORG 用于声明一个数据缓冲池的开始
AREA Example ,CODE , READONLY
start BL func1
func1 ;子程序
;code
LDR R1 ,=0x55555555 ;LDR R1,[PC,#offest to literal pool 1]
;code
MOV PC ,LR ;子程序结束
LTORG ;定义数据缓冲池&55555555
DATA SPACE 4200 ;从当前位置开始分配4200字节的内存单元
END ;默认的数据缓冲池为空
MAP
MAP 定义内存表的首地址,与FIELD配合使用来定义结构化的内存表结构。^为MAP的同义词
MAP 0x80, R9 ;内存表的首地址为R9+0x80
FIELD
FIELD 定义内存表中的数据域。#是FIELD的同义词。MAP与FIELD仅是定义数据结构,不分配内存单元。
MAP 0 ;内存表的首地址为0
consta FIELD 4 ;consta长度为4字节,相对位置为0
constb FIELD 4 ;constb长度为4字节,相对位置为4
x FIELD 8 ;x长度为8字节,相对位置为8
y FIELD 8 ;y长度为8字节,相对位置为16
string FIELD 256 ;string长度为256字节,相对位置为24
LDR R6,consta ;引用内存表中的数据域
MAP 4096 ;内存表的首地址为4096(0x1000)
consta FIELD 4 ;consta长度为4字节,相对位置为0
constb FIELD 4 ;constb长度为4字节,相对位置为4
x FIELD 8 ;x长度为8字节,相对位置为8
y FIELD 8 ;y长度为8字节,相对位置为16
string FIELD 256 ;string长度为256字节,相对位置为24
MOV R9 ,#4096
LDR R5 ,[R9,constb] ;将内存表中的数据域constb读取到R5中。
在arm-thumb指令中,通常将R9作为静态基址寄存器。
MAP 0,R9 ;内存表的首地址为R9+0
consta FIELD 4 ;consta长度为4字节,相对位置为0
constb FIELD 4 ;constb长度为4字节,相对位置为4
x FIELD 8 ;x的长度为8字节,相对位置为8
y FIELD 8 ;y的长度为8字节,相对位置为16
string FIELD 256 ;string长度为256,相对位置为24
可以通过下面的指令方便地寻址超过4KB的数据
ADR R9, DATASTART ;ADR指令将PC值或者寄存器的值读取到寄存器,它是基于PC值进行计算
LDR R5,constb ;相当于LDR R5 ,[R9,#4]
Datastruc SPACE 280 ;分配280字节的内存单元
MAP Datastruc ;内存表的首地址为Datastruc内存单元
consta FIELD 4 ;consta长度为4字节,相对位置为0
constb FIELD 4 ;constb长度为4字节,相对位置为4
x FIELD 8 ;x的长度为8字节,相对位置为8
y FIELD 8 ;y的长度为8字节,相对位置为16
string FIELD 256 ;string长度为256,相对位置为24
LDR R5 ,constb ;相当于LDR R5, [PC, offest]
当FIELD 伪指令中的操作数为0时,其中的标号即为当前内存单元的地址
SPACE
SPACE 用于分配一块内存单元,并用0初始化。 %是SPACE的同义词
Datastruc SPACE 1000 ;分配1000个字节单元,并将内存单元内容初始化为0
DCB 用于分配一片连续的字节内存。 =是DCB 的同义词
{label} DCB expr{,expr}{,expr}…
其中:
label 内存块起始地址标号。
expr可以为-128~255 的数值或字符串。内存分配的字节数由expr 个数决定。
Nullstring DCB "Null string“ ,0 ;构造一个以NULL结尾的字符串
DCD及DCDU、DCDO,DCFD及DCFDU、DCFS及DCFSU、DCI、DCQ及DCQU、DCW及DCWU可以参照。
4.1.3汇编控制伪指令
IF、ELSE及ENDIF
WHILE及WEND
MACRO及MEND
MEXIT
IF、ELSE及ENDIF
IF、ELSE及ENDIF 用于选择
IF Version =”1.0“
;指令
;伪指令
ELSE
;指令
;伪指令
ENDIF
WHILE 及WEND
WHILE及WEND 循环
count SETA 1 ;设置循环计数变量count初始值为1
WHILE count <=4 ;由conut控制循环次数
count SETA count+1 ;将循环计数变量加1
;code
WEND
MACRO及MEND
MACRO及MEND 定义宏
MACRO ;宏定义开始
$label xmac $p1 ,$p2 ;宏的名称为xmac,有两个参数$p1、$p2
;宏的标号$lable可用于构造宏定义体内的其他标号名称
;code
$lable.loop1 ;code ;$lable.loop1为宏定义体内的内部标号
;code
BGE $label.loop1
$label.loop2 ;code
BL $p1 ;参数$p1为一个子程序的名称
BGT $label.loop2
;code
ADR $p2
;code
MEND ;宏定义结束
;在程序中调用宏
abc xmac subr1 ,de ;通过宏的名称xmac调用宏,其中宏的标号为abc,
;参数1为subr1,参数2为de
;程序被汇编后,宏展开的结果
;code
abc.loop1 ;code ;用标号$label实际值abc代替$label
;code
BGE abc.loop1
abc.loop2 ;code
BL subr1 ;参数1的实际值为subr1
;code
ADR de ;参数2的实际值为de
MEXIT
MEXIT 用于从宏中跳转出去
MACRO
$abc macroabc $p1 ,$p2
;code
WHILE condition1
;code
IF condition2
;code
MEXIT ;从宏中跳转出去
ELSE
;code
ENDIF
WEND
;code
MEND
4.1.4 信息报告伪指令
ASSERT 条件不成立时显示告警信息
INFO 报告信息
OPT 设置列表选项
TTL及SUBT 插入标题及子标题
4.1.6 其他伪指令
ALLGN
AREA
CODE16及CODE32
END
ENTRY
EQU
EXPORT或GLOBAL
EXTERN
GET或INCLUDE
IMPORT
INCBIN
KEEP
NOFP
REQUIRE
REQUIRE8及PERSERVER8
RN
ROUT
ALLGN
ALLGN 指定对齐方式
AREA cacheable ,CODE, ALLGN=3 ;指定下面的质量是8字节对齐
rout1 ;code
;code
MOV PC ,LR ;程序跳转后变成4字节对齐
ALLGN 8 ;指定下面的指令是8字节对齐
rout2 ;code
AREA
AREA 定义一个代码段或者数据段
AREA Example ,CODE ,READONLY ;定义一个代码段,名称为Example,属性为READNOLY
CODE16及CODE32
CODE16 表明后面的指令为thumb指令
CODE32表明后面的指令为arm指令
END
END 表示源程序结尾
ENTRY
ENTRY 指定程序入口点
EQU
EQU 用于取别名,*为其同义词,相当于C语言中的#define。
abcd EQU 2 ;定义abcd代表2
addr1 EQU 0x1c ,CODE32 ;定义addr1符号值为绝对地址0x1c,而且该指令为arm指令
EXPORT及GLOBAL
EXPORT 声明一个符号可以被其他文件引用,相当于声明了一个全局变量。GLOBAL是EXPORT的同义词
AREA Example ,CODE ,READONLY
EXPORT Doadd ;下面的函数名称Doadd可以被其他源文件引用
Doadd ADD R0,R0,R1
EXTERN
EXTERN 声明一个符号是在其他源文件中定义的。
AREA Example ,CODE ,READONLY
EXTERN _CPP_INITIALIZE[WEAK] ;如果连接了C++库则读取函数_CPP_INITIALIZE地址
LDR R0 ,_CPP_INITIALIZE
CMP R0 ,0 ;
BEQ nocplusplus ;如果没有连接C++库,则跳转到nocplusplus
GET及INCLUDE
GET 将一个文件包含到当前文件中,INCLUDE是GET同义词
AREA EXAMPLE ,CODE, READNOLY
GET file1.s ;包含源文件file1.s
GET C:/project file/file2.s ;包含源文件file2.s,可以包含路径中的空格
IMPORT
IMPORT 引入外部定义符号
INCBIN
INCBIN将文件包含到当前文件中,但是被包含的文件不进行汇编处理
AREA Example ,CODE,READONLY
INCBIN file1.dat ;包含文件file1.dat
INCBIN C:/projecfile/file2.txt ;包含文件file2.txt,路径中不能有空格
KEEP
KEEP将局部符号包含到目标文件的符号表中
NOFP
NOFP 禁止浮点运算
PREQUIRE
PREQUIRE 指定段之间的依赖关系
REQUIRE8及PRESERVER8
REQUIRE8 要求当前代码中数据栈8字节对齐
PRESERVE8要求当前代码中数据栈8字节对齐
RN
RN 为某一个寄存器定义名称,即更改名称
ROUT
ROUT 定义局部变量的有效范围