LDR/STR架构:CPU不能直接处理内存,只能读寄存器,因此需要将内存的内容拷贝到寄存器后再处理。
LDR(load register):内存->寄存器;
STR(store register):寄存器->内存;
8种寻址方式
- 寄存器寻址: mov r1, r2 //把r2的内容移动到r1;
- 立即寻址: mov r0, #0xff00 //把数字0xff00移动到r0;
- 寄存器移位寻址: mov r0,r1,lsl#3 //把r1的内容左移3位(乘8)后再放入r1;
- 寄存器间接寻址: mov r0,[r2] //以r2内的数据为目标地址把数据移动到r0;
- 变址寻址: mov r1,[r2,#4]//以r2内的地址加4作为最终目标地址访问内存,把内存的数据移动到r0;
- 多寄存器寻址: ldmia r1!,{r2-r7,r12} 以r1内存的地址为首地址,连续向后访问8个地址,分别移动到R2-R7和r12中;
- 堆栈寻址: stmfd sp!,{r2-r7,lr} 以SP指向的内存的地址为首地址,连续向后访问8个地址,分别移动到R2-R7和lr中;
- 相对寻址: beq flag 跳转到标号flag位置去运行;
- B(byte) 功能不变,操作长度变为8位;如ldrb
- H(half word) 功能不变,操作长度变为16位;如ldrh
- S(signed) 功能不变,操作数为有符号位;如ldrsb,ldrsh;
- S(S标志) 功能不变,影响CPSR,运算结果为0将CPSR中的z位变成1;
条件满足才执行;
- moveq r0,r1 如果eq(上一行语句的结果(CPSR的z位为1))成立则执行本条语句,类似if(z==1){r0=r1};仅影响自己,不影响前后语句。
- movne r0,r1 如果ne(上一行语句的结果(CPSR的z位为0))成立则执行本条语句,类似if(z==0){r0=r1};仅影响自己,不影响前后语句。
取数据->解码->执行;同时执行,在执行的时候解码,解码下一句,读取下下一句;
pc指向的是取数据的地址,因此有时候在中断返回的时候需要将PC的值减去8;
spv2150一共有13级流水
- mov r1, r2 只能操作寄存器,把r2的内容移动到r1;
- mvn r1, r2 只能操作寄存器,把r2的内容按位取反后移动到r1;
- add 加
- sub 减
- and 逻辑与
- orr 逻辑或
- eor 逻辑异或
- bic r0,r1,#0x1f 位清除;将r1中的0x1f为1的位清零后给r0;
- spsr和cpsr访问指令:每个模式都有1个独立的spsr,整个芯片只能有1个cpsr,spsr就是用来保存当前模式的cpsr,便于跳转后回来时恢复。
- mrs r0, cpsr 读CPSR;CPSR->R0
- msr cpsr, r0 写CPSR;R0->CPSR
没有结果,只改变cpsr的z位。
- cmp r0,r1 比较r0、r1是否相等,相减后结果为0,
- cmn r0,r1 比较r0、r1是否互为补数,相加后结果是否为0,
- test r0 #0x01 测试r0的第0位是否为1.
- teq r0,r1 比较r0、r1是否相等,两个数异或,
- b直接跳转,且不回来
- bl跳转前先将地址存lr地址,回来后接着执行,例如函数调用;
- ldr(load register):内存->寄存器;
ldr r0, = 0x11111111 //有=号表示该指令伪指令
- str(store register):寄存器->内存;
str r0,[r1] //把R0的值写入到R1存储的地址的内存。
- ldm 多个内存->寄存器;
- stm 多个寄存器->内存;
swp r1,r2,[r0];将r0指向的内存的数据给r1,将r2的数据移动到r0中内存的地址中。
swp r1,r1,[r0];交换r1与r0指向的内存,将r0的存的地址的内容放到r1,将r1的数据移动到r0中内存的地址中。
mrc 读取cp15;
mrc p15,0,r0,c1,c0,0;将cp15的c1寄存器读取到r0;
mcr 写cp15;
mcr p15,0,r0,c1,c0,0;将寄存器r0的内容写入cp15的c1;
stmia sp,{r0-r12};将r0-r12读取放在以sp为首地址的后面13个寄存器,每次存一次后地址再加4;
stmib sp,{r0-r12};将r0-r12读取放在以sp为首地址的后面13个寄存器,每次地址加4后再存;
后缀ia:先传输,再地址加4
后缀fb:先地址加4,再传输;(常用,行业默认使用)
后缀da:先传输,再地址减4
后缀db:先地址减4,再传输;
与编译器有关,不同编译器,伪指令不同
@ 汇编注释,也可使用//
: 标号
. 当前指令地址,类似while,b .
# 立即数
.ldr 大范围的地址加载(长范围),该伪指令不用判断数据的合法性;如ldr r0,=0xfff;将立即数放入R0,
.adr 小范围的地址加载(附近),该伪指令不用判断数据的合法性;如ldr r0,=0xfff;将立即数放入R0,
.section
伪指令,用于给代码去段名
__HEAD .section ".head.text","ax"//给接下来的代码取一个段名.head.text,用户自定义段。