常用ARM指令
mov 例:mov r1 r2 @两个寄存器数据之间的传递
mvn 与mov的区别是:mov是原封不动的将数据传输,而mvn是将数据按位取反后再传递
2. 算术指令
add sub rsb adc sbc rsc
3. 逻辑指令
and orr eor bic
4. 比较指令
cmp cmn tst tep
比较指令的特殊性:比较指令不用添加S后缀就可以影响CPSR的标志位。
5. 乘法指令
mvl mla nmull umlal smull smlal
6. 前导零计数
clz
7. CPSR访问指令 (CPSR比较特殊,需要专门指令来访问)
mrs / msr mrs用来读cpsr,msr用来写
CPSR和SPSR两个寄存器的区别与联系: CPSR是程序状态寄存器,整个SOC上只有1个,而SPSR有5个,分别在5种异常模式下,作用是当从普通模式进入异常模式
8. 跳转指令
b bl bx
b:直接跳转(不用保存返回地址)
bl: 跳转前把返回地址放入到lr中,以便返回,用于函数调用
bx:跳转同时切换到ARM模式,一般用于异常处理跳转
9. 访问内存指令
ldr/str ldm/stm swp
ldr/str: 字节、半字、字的访问
str:该指令将寄存器的内容存入到内存空间。
ldm/stm:多字批量访问
swp r1, r2, [r0] 寄存器和内存交换内容
swp r1, r1, [r0] @将r0存的内容送给前面r1寄存器,再将后面r1寄存器的内容传给内存r0
ARM汇编的立即数:合法立即数和非法立即数
ARM指令本身是32位的,除了指令标志和操作标志外,本身只能带很少位数的立即数。
合法立即数:经任意位数的移位后非零部分可以用8位表示。
10. 软中断指令
swi 主要用来实现操作系统的系统调用。
!的作用:
例:ldmia r0!, {r2 – r3}
感叹号的作用就是将r0的值在ldm过程中的增加或者减少最后写到r0中去,也就是ldm过程中会改变r0的值。
^的作用:
例:
ldmfd sp!,{r0-r6,pc}^
^的作用:在目标寄存器中有pc时,会同时将SPSR写入CPSR,一般用于从异常处理模式返回。
GNU汇编的一些符号
1. @ 用来做注释
2. # 用来注释
3. : 以冒号结尾的是标号,表地址
4. . 表示当前指令的地址 @汇编循坏 b .
5. # 立即数面前要加#和$
GNU常用的伪指令
1. .global_start @给_start外部链接属性
2. .section .text @指定当前断为代码段
3. .ascii .byte .short .long .word .quad(双字) .float .string @定义数据
汇编数据定义举例:
IRQ_START:
.word 0xcaffffff
等价于C语言
unsigned int IRQ_SRART = 0xcaffffff;
4. .align 4 @以16字节对其 2^4 = 16
5. .balignl 16 0xabcfdcac @以16字节对其填充,填充内容为 0xabcfdcac
b: 表示位填充; align 表示要对齐; l 表示long,以4字节为单位填充; 16 表示16字节对齐
6. .equ @相当于C的宏定义
7. .end @标识文件结束
8. .include @头文件包含
9. .arm / .code32 @声明以下为ARM指令
10. .thumb / .code16 @声明以下为thumb指令
GNU重要的几个伪指令
1. ldr 大范围的地址加载指令
2. adr 小范围的地址加载指令
3. adrl 中等范围的地址加载指令
4. nop 空操作
ARM中一般有一个ldr指令和一个ldr伪指令,为了避免数据的合法性,常用ldr伪指令。
adr总是以PC为基准来表示地址,指令本身和地址有关,可以用来检测程序当前运行地址在哪个地方。
ldr加载的地址和连接时给定的地址有关,由连接脚本决定。
8种寻址方式
1. 寄存器寻址 例:mov r1,r2 ;将r2的内容赋给r1
2. 立即寻址 例:mov r0,#0x0f ;’#’表示后面是一个数,本指令的意思是将0x0f赋给r1
3. 寄存器移位寻址 例:mov r0, r1,lsl#3 ;将r1左移3位后赋给r1
4. 寄存器间接寻址 例:ldr r1, [r2] ;把r2的内存地址赋给r1
5. 基址变址寻址 例:ldr r1,[r2, #4] ;把r2地址加4再赋给r1
6. 多寄存器寻址 例:ldmia r1! , {r2-r7,r12} ;以r1地址为基地址,和以后的地址依次存到r2-r7和r12中 r1可以看作是一个数组的首地址
7. 堆栈寻址 例:sdmst fp! , {r1-r7,lr}
;用意跟ldmia一样,只是此时是将堆栈里的地址依次放入r1-r7,lr
8. 相对寻址 例:bep flag flag: ;标号表示入口地址(如函数)