水龙吟的备忘录 2016-05-28
ARM汇编指令集:
指令:汇编指令是CPU机器指令的助记符,经过编译后会得到一串1、0组成的机器码,可以由CPU读取执行
伪指令:在编译过程中间起作用,用来指导编译过程,经过编译后不会生成机器码
***ARM汇编特点1:LDR/STR架构:在RISC架构中,cpu读写内存需要通过CPU内部的寄存器(CISC的CPU可以直接和内存通信)
***ARM汇编特点2:8中寻址方式
#寄存器寻址 mov r1,r2 把r2里面的内容送到r1里面去(寄存器靠名字找的)
#立即寻址(立即数) mov r0,#0xFF00 加#表示数字
#寄存器移位寻址 mov r0, r1, lsl #3 lsl左移指令,把r1的值左移三位,然后把左移后生成的那个数赋值给r0
#寄存器间接寻址 ldr r1, [r2] [r2]表明内存地址存在r2中 ,然后把内存地址里面存储的那个值赋给r1
基址变址寻址 ldr r1, [r2, #4]
[r2,#4]中存储的地址为r2中的地址+4构成的地址,r2里面存储的地址称为基地址,后面的数字就是需要的变址数 这条指令的意思:把r2存储的内存地址加4的地址的值赋值给r1
#多寄存器寻址 ldmia r1!, {r2-r7, r12}
一次访问多个寄存器//////r1放的内存地址,把r1理解为数组,r2-r7,r12表示7个寄存器,
这句指令的意思就是:r1当中存储的内存地址为基地址,然后把从这个地址开始的连续七个地址当中存储的值,依次放在后面对应的寄存器中
#堆栈寻址 stmfd sp!, {r2-r7, lr}
#相对寻址 beq flag
flag: 标号
***ARM汇编特点3:指令后缀
同一指令经常附带不同后缀,变成不同的指令。经常使用的后缀有:
B(byte)功能不变,操作长度变为8位
H(half word)功能不变,长度变为16位
S(signed)功能不变,操作数变为有符号
如 ldr ldrb ldrh ldrsb ldrsh
S(S标志)功能不变,影响CPSR标志位 一般用在数据传输指令
如 mov和movs movs r0, #0
***ARM汇编特点4:条件执行后缀
mov r0,r1 @相当于C语言的 r0 = r1
moveq r0,r1 @如果eq后缀成立,则执行本句指令,反之,则不执行
条件后缀执行注意两点:
1.条件后缀是否成立,不是取决于本句代码,而是取决于这句代码之前的代码运行后的结果
2.条件后缀决定了本句代码是否会执行,而不会影响上一句或下一句代码是否会执行
***ARM汇编特点5:多级指令流水线
pc指向正在被取指的指令 ,而非正在执行的指令
******数据传输指令
mov r1,r0 @两个寄存器之间传递数据
mov r1,#12fff @把立即数赋值给目标寄存器
mvn 和 mov 用法一样 区别是mov原封不动传递 ,mvn是按位取反传递
******逻辑指令
and 逻辑与
orr 逻辑或
eor 逻辑异或
bic 位清除指令 bic r0,r1,#0x1f 将r1中的数的bit0到bit4 (#0x1f为1的位清零)清零后赋值给r0
******比较指令
cmp
cmn 看两个值是否互补
tst test r0,#0xf @测试r0的0~3位是不是为0
teq 测试等价
比较指令用来比较两个寄存器中的数
比较指令不用后加S后缀就可以影响cpsr中的标志位
******常用ARM指令
cpsr访问指令: mrs & msr
mrs用来读psr ,msr 用来写psr
cpsr寄存器比较特殊,需要专门的指令访问,这就是mrs和msr
******跳转指令
b & bl & bx
b: 直接跳转
bl(branch and link) :跳转前把返回地址放入lr中,以便返回,用于函数调用
*******访存指令
ldr /str / ldm / stm / swp
单个字/半字/字节访问 : ldr/str
多字批量访问 :ldm/stm
swp:内存和寄存器互换指令
swp r1,r2,[r0] 把r0存的地址的内容放到r1里面去,然后把r2的内容放到r0存的地址的内存中去
swp r1,r1,[r0]
******************************
合法立即数与非法立即数
ARM指令都是32位,除了指令标记和操作标记外,本身只能附带很少位数的立即数。因此立即数有合法和非法之分。
合法立即数:经过任意位数的移位后非零部分可以用8位表示的即为合法立即数
**************
协处理器cp15的操作指令
mcr& mrc
mrc用于读取cp15中的寄存器
mcr用于写入cp15中的寄存器
*******************
由于ldr/str每周期只能访问4字节内存,如果需要批量读取,写入内存时太慢,解决的方案就是ldm/stm
ldm/stm与栈的处理
ldm (load register mutiple)
stm (store register mutiple)
****************************************************************
!的作用:r0值在ldm过程中发生的增加或减少写回到r0去,也就是ldm在运算过程中会改变r0中的地址值,如果没有!,则r0中的地址值不发生变化,如果有!,则r0中的值,会发生相应的改变
ldmia r0,{r2,r3}
ldmia r0!,{r2,r3}
^的作用:在目标寄存器中有PC时,会同时将spsr写入到cpsr(异常返回的时候)
ldmfd sp!,{r0-r6,pc}
ldmfd sp!,{r0-r6,pc}^
四种栈
空栈: 空栈就是当需要往栈中加入内容的时候,直接将内容存入栈指针所指向的地址空间,然后在将栈指针指向下一个空的地址空间,而要取出内容时则需要先移动指针才能去除
满栈: 满栈就是栈指针始终指向栈的最后一格,每次需要存储内容时,都需要先移动栈指针,然后把你内容存入栈指针所指向的地址空间,当要取出内容的时候不用移动指针直接可以取出
增栈 栈指针移动的时候,往地址值增加的方向移动
减栈 栈指针移动的时候,往地址值减小的方向移动
**********************************************************
伪指令
@用来做注释
#做注释一般用来放做行首,表示这一行都是注释而不是代码
:以冒号结尾的是标号
.点号 在gnu汇编中表示当前指令的地址
立即数前面要加#或者$,表示这个数是立即数