还是来从结构开始吧。
一个完整的ARM汇编程序包括处理器框架定义、数据段、代码段、与main函数。
分开来看
处理器框架定义
.arch指定了ARM处理器框架
.fpu指定了协处理的类型
.eabi_attribute注定了一些接口属性
段定义
ARM汇编使用.section指令来定义段,格式为
.section name[,”flags”[,%type[,flag_specific_arguments]]]
name为段名,flags为段的属性,如读写可执行等,type指定了段的类型
flag_specific_arguments指定了一些平台的参数
此外还有注释于标号,汇编器指令,就不列举了。
ARM处理器寻址方式
1.立即寻址
MOV R0, #1234
2.寄存器寻址
执行后RO=1234。立即数以#作为前缀
MOV R0,R1
3.寄存器移位寻址
LSL:逻辑左移
LSR:逻辑右移
ASR:算术右移,移动过程中符号位保持不变
ROR:循环右移
RRX:带扩展的循环右移
4.寄存器间接寻址
寄存器间接寻址中地址码的寄存器是操作数的指针
LDR R0, [R1]
指令的功能是将R1寄存器的数值作为地址,去除此地址中的值赋给R0寄存器
5.基址寻址
基址寻址多用于查表、数组访问等操作
LDR 40 [R1,#-4]
指令功能是将R1寄存器的数值减4作为地址,取出此地址的值赋给R0寄存器。
6.多寄存器寻址
最多可以完成16个通用寄存器的传送
LDMIA R0,{R1,R2,R3,R4}
LDM是数据加载指令,后缀的IA表示吗,每次执行完加载操作后R0寄存器的值+1个字,在ARM指令集中,字表示的是一个32位的数值。这条指令执行后R1=[R0],R2=[R0+#4],R3=[R0+#8],R4=[R0+#12].
前面说#表示16进制,一个十六进制数需要8位二进制来表示,这就是为什么+#4的原因
7.堆栈寻址
堆栈寻址是ARM处理器特有的一种寻址方式,堆栈寻址需要特定的指令来完成。
多采用LDM/STM前缀,FA、EA、FD、ED为后缀
STMFD SP!, {R1-R7, LR} @将R1~R7,LR入栈。
LMDFD SP!, {R1-R7, LR} @将数据入栈,放入R1~R7,LR寄存器。
8.块拷贝寻址
块拷贝寻址可实现连续地址数据从存储器的某一个位置拷贝到另一位置
同样采用多寄存器
LDMIA R0! , {R1-R3} @从R0寄存器只想的存储单元中读取3个字到R1-R3寄存器
STMIA R0! , {R1-R3} @存储R1-R3寄存器的内容到R0寄存器指向的存储单元
9.相对寻址
相对于程序计数器PC的当前值为基地址
BL NEXT
…
NEXT:
…
剩下的还有很多ARM汇编指令就不列举啦