文章转自:https://blog.csdn.net/qqliyunpeng/article/details/48791311
一、简介:
ARM体系架构中,是不允许cpu直接访问内存单元。
为了解决访问内存单元的需要,使用寄存器作为中继,内存和寄存器通过load/store指令交互,cpu在访问寄存器。
内存单元 和 寄存器 直接的数据交互。
单寄存器指令 ldr str多寄存器指令 ldm stm交互指令 swp
二、单寄存器指令:
(1)指令功能:1个寄存器和1个内存单元数据交互。
ldr 内存单元 ----> 寄存器 (l是left)红字的部分只适用于单寄存器指令,多寄存器指令正好相反
str 寄存器 ----> 内存单元(t是to)
(2)语法格式 :
LDR{<cond>}{<size>} Rd, <address>
STR{<cond>}{<size>} Rd, <address>
{} :可选
{<cond>} :条件码
{<size>} :传送单元大小
Rd :寄存器
<address> :内存地址
(3)<address> :
1 --- 标号寻址 (地址的助记符)
str r1,val @ *(val) = r1
val:
.word 0x11223344
2--- 寄存器间接寻址
mov r0,#0x41000000
str r1,[r0] @ *(r0) = r1
3--- 基址变址寻址
mov r0,#0x41000000
str r1,[r0,#4] @ *(r0+4) = r1
(4)基址变址寻址偏移量的三种形式 :
1--- 立即数 str r1,[r0,#4]
2--- 寄存器 mov r2,#4
str r1,[r0,r2]
3--- 寄存器移位 mov r2,#1
str r1,[r0,r2,lsl #2]
(5)基址变址的三种方式 :
1-- 前索引 str r1,[r0,#4] @ *(r0+4) = r1 类似 *(p+1)
2-- 自动索引 str r1,[r0,#4]! @ r0 =r0+4 *(r0)=r1 类似 *(++p) p=p+1、*p
3-- 后索引 str r1,[r0],#4 @ *(r0)=r1 r0 =r0+4 类似 *p++
*p、p=p+1
(6)ldr指令和ldr伪指令的区别 :--易混淆部分举例
第一组:
ldr r0,=0xff @ r0=0xff
mov r1,#0xff @ r0=*(0xff)
ldr r0,[r1]
第二组:
ldr r0, =val @ r0 =val地址
ldr r0,val @ r0 =*(val的地址)
val
.word 0x41000000
(7){<size>} :传送单元大小
指定指令访问内存单元中的几个字节 4个、2个、1个
4个 :默认
2个 :H
1个 :B
低位优先使用,高位补0
三、多寄存器指令 :
(1)指令功能:多个寄存器和多个内存单元数据交互。
ldm 内存块 ---给-> 多个寄存器
stm 多个寄存器 ---给-> 内存块
(2)指令的格式:
<LDM>{<cond>}<addressing_mode> Rb{!}, <寄存器 list>
<STM>{<cond>}<addressing_mode> Rb{!}, <寄存器 list>
{<cond>} :条件码(可选)
<addressing_mode> :地址模式
Rb : 内存块的首地址
{!} :是否更新基址
<寄存器 list> :寄存器列表
(3) <addressing_mode> :地址模式
I --- 加
D --- 减
A --- 后 :地址后操作
B --- 先 :地址先操作
IA --- 先操作数据,再操作地址(加)
IB --- 先操作地址(加),再操作数据
DA --- 先操作数据,再操作地址(减)
DB --- 先操作地址(减),再操作数据
(4) <寄存器 list> :寄存器列表
寄存器列表写法:
1-- 罗列
{r1,r2,r3,r4,r7}
2-- 连续的寄存器可以缩写
{r1-r4,r7}
例子:
mov r4,#0x41000000
stmia r4!,{r0-r3}
注意:
存储顺序与寄存器列表的顺序无关,永远都是小号寄存器对应小地址。
大括号中无论怎么排列,都是r0放在0x41000000地址上
四、多寄存器指令对栈的操作 :
(1) ldm -- 出栈 --- pop
stm -- 压栈 --- push
(2)栈操作的地址模式
F 满 --- sp指向的空间,有数据
E 空 --- sp指向的空间,无数据
D 减 --- 栈向地址减小的方向增长
A 增 --- 栈向地址增大的方向增长
(3)ARM体系结构下,栈都是满减的栈
满减栈(fd)
stmfd -- 压栈 --- (--i) --相当于地址先减1,再在地址上放数据
这里说明在压栈的时候地址指针sp指向了栈顶的上一个元素
ldmfd -- 出栈 --- (i++) --相当于先将地址上的数据取走,地址再加
五、ARM的寻址方式:
8种:
立即数寻址
寄存器寻址
寄存器间接寻址
寄存器移位寻址
基址变址寻址
多寄存器寻址
相对寻址
堆栈寻址