寻址方式就是CPU根据指令中的地址信息,找出物理地址也就是内存地址的方式,通俗理解就是ARM指出内存地址的方式。

寻址的目的就是找出操作数,比如ARM要做一个除法运算,就需要除数和被除数,除数和被除数都是除法指令的操作数,要找到这些操作数,可以有多种方法,寻找操作数的过程就叫做寻址。(我个人理解)

ARM支持九种寻址方式:

  • 立即数寻址
  • 寄存器寻址
  • 寄存器偏移寻址
  • 寄存器间接寻址
  • 寄存器基址变址寻址
  • 多寄存器寻址
  • 相对寻址
  • 堆栈寻址
  • 块拷贝寻址

1.立即数寻址

立即数寻址就是直接将内存中的数据发给CPU作为操作数。注意,由于ARM是32位指令集,所以立即数的范围不可以超出0255,也就是说立即数的范围只能是0255。

格式:就是在立即数前面加上 # 来作为操作数

典型的例子就是直接对寄存器进行写值:

ldr r0, #254   ;将254写入r0寄存器
add r1, r2, #3 ;将r2寄存器中的值与3相加后,在写入r1寄存器

2.寄存器寻址

寄存器寻址就是直接将寄存器中的数值作为操作数:

ldr r1, r0      ;将r0寄存器中的值写到r0
add r3, r2, r1 ;将r1、r2寄存器的值相加,结果写入r3寄存器

3.寄存器间接寻址

还是利用了寄存器,只不过操作数不是寄存器中的值了,操作数在内存中,那怎么办?没事,操作数的地址就在寄存器中。所以寄存器间接寻址相当于以寄存器中的值作为内存地址,去内存中寻找操作数。

格式:在提供操作数地址的寄存器上加上[],比如[r0]

mov r0, #0X54000032
ldr r1, [r0] ;将地址为0X54000032的数据写入r1寄存器中

4.寄存器偏移寻址

以寄存器寻址为本,将寄存器中的数移位后作为操作数。

一共有6中移位操作:

LSL:逻辑左移(Logical Shift Left),寄存器中字的低端空出的位补0。

LSR:逻辑右移(Logical Shift Right),寄存器中字的高端空出的位补0。

ASL:算术左移(Arithmetic Shift Left),和逻辑左移LSL相同。

ASR:算术右移(Arithmetic Shift Right),移位过程中符号位不变,即如果源操作数是正数,则字的高端空出的位补0,否则补1。

ROR:循环右移(Rotate Right),由字的低端移出的位填入字的高端空出的位。

RRX:带扩展的循环右移(Rotate Right eXtended),操作数右移一位,高端空出的位用进位标志C的值来填充,低端移出的位填入进位标志位。

格式:rx, 移位命令 移位操作数

ldr r0, r1, lsl #3   ;将r1的值逻辑左移3位后写入r0
ldr r0, r1, ror r2 ;将r1的值循环右移r2中的值对应位后,写入r0

5.寄存器基址变址寻址

基址变址寻址是基于寄存器间接寻址的,只不过地址不再是寄存器中的值了,而是偏移后的值,这里的偏移值可以理解为地址相加值。

加上感叹号应该有优先执行的意思吧(个人理解)

格式:[rx, n],表示在rx寄存器所指向的地址上,再偏移(相加)n字节

ldr r0, [r1, #3]     ;地址为:r1值+3字节,指令执行完r1不变
ldr r0, [r1, #3]! ;地址为:r1值+3字节,指令执行完r1+3
ldr r0, [r1, #-1] ;地址为:r1值-1字节,指令执行完r1不变
ldr r0, [r1, r2] ;地址为:r1值+r2值
ldr r0, [r1], #4 ;地址为:r1值,但指令执行完后,r1值+4字节

6.批量寄存器寻址

批量寄存器寻址就是使用一个大括号{}包含多个寄存器

ldmia r0, {r1, r2, r3, r4}     ;将r1,r2,r3,r4中的数据依次放入R0指向的内存地址,r0+4指向的内存地址...
ldmia r0, {r1-r4} ;同上。

7.相对寻址

通过标号进行寻址,经常与跳转指令相配合使用

	bl heihei 

heihei:        ;跳转到heihei执行

8.堆栈寻址

堆栈即Stack,因为CPU的寄存器总是及其有限的,很多时候我们不得不使用内存来存储数据,比如进行多级跳转的时候,这时候堆栈就是一个很好的工具,每次跳转就将当前函数的返回地址存储到内存,最底层被调用的子函数会最先返回,就先将压入栈的现场返回,以此类推…,ARM使用SP(R13)作为栈指针,ARM设计的内存栈模型有2×2=4种

按照栈在内存增长的方向分为递增栈和递减栈 :

递增(Increase) 堆栈:向堆栈写入数据时,堆栈由低地址向高地址生长。

递减(Descend) 堆栈:向堆栈写入数据时,堆栈由高地址向低地址生长。

根据堆栈指针SP指向的位置,又可以把堆栈分为满堆栈和空堆栈两种。

满堆栈(Full Stack):SP始终指向栈顶元素,压栈的时候先移动SP,再将数据放入SP指向的地址。

空堆栈(Empty Stack):SP始终指向下一个将要放入元素的位置,压栈时先将数据放入SP指向的地址,再移动SP

最后,可以得到4种基本的堆栈类型:

满增栈(FA):堆栈指针指向最后压入的数据,且由低地址向高地址生长。

满减栈(FD):堆栈指针指向最后压入的数据,且由高地址向低地址生长。常用这种

空增栈(EA):堆栈指针指向下一个将要压入数据的地址,且由低地址向高地址生长。

空减栈(ED):堆栈指针指向下一个将要压入数据的地址,且由高地址向低地址生长。

stmfd sp!, {r1-r7, lr}  ;将r1到r7和lr的数据压入fd栈

9.块拷贝寻址

块拷贝寻址提供了一块内存和一组寄存器之间的拷贝,按照内存使用方式的不同,可以分为2×2=4种。地址增方向/地址减方向×先偏移/后偏移。堆栈寻址就可以看作是块拷贝寻址的的一个实例。

即:

IB:Increment Before Operating

IA:Increment After Operating

DB:Decrement Before Operating

DA:Decrement After Operating

STMIA  R0!,{R1—R7}  ;将R1-R7的寄存器中的值放入R0指向的地址,R0自动更新,指向操作后的地址

参考

ARM的九种寻址方式的更多相关文章

  1. ARM的9种寻址方式

    立即寻址 操作数是立即数,以“#”为前缀,表示 16 进制数值时以“0x”表示. 例: MOV   R0,#0xFF00   ;0xFF00 ->  R0 SUBS   R0,R0,#1     ...

  2. ARM指令分类及其寻址方式

    ARM指令分类及其寻址方式 一:ARM指令的分类 ARM指令集可以分为以下6类: •跳转指令: •数据处理指令: •程序状态寄存器(PSR)传输指令: •load/store指令: •协处理器指令: ...

  3. 浅谈UML的概念和模型之UML九种图

    1.用例图(use case diagrams) [概念]描述用户需求,从用户的角度描述系统的功能 [描述方式]椭圆表示某个用例:人形符号表示角色 [目的]帮组开发团队以一种可视化的方式理解系统的功能 ...

  4. UML九种图作用简介

    UML(统一建模语言):是面向对象的可视化建模语言. UML中有3种构造块:事物.关系和图,事物是对模型中最具有代表性的成分的抽象,关系是把事物结合在一起,图聚集了相关的事物 UML中有九种图如下: ...

  5. [UML]转:浅谈UML的概念和模型之UML九种图

    转自:http://blog.csdn.net/jiuqiyuliang/article/details/8552956 目录: UML的视图 UML的九种图 UML中类间的关系 上文我们介绍了,UM ...

  6. UML 小结(6)- UML九种图的比较与学习

    UML中的九种图: 用例图.类图.对象图.状态图.时序图.协作图.活动图.部署图.构件图. 1)用例图(Use Case Diagram) 它是UML中最简单也是最复杂的一种图.说它简单是因为它采用了 ...

  7. AngularJS 的那些内置九种过滤器

    ng内置了九种过滤 1. currency (货币处理) 使用currency可以将数字格式化为货币,默认是美元符号,你可以自己传入所需的符号,例如我传入人民币: {{num | currency : ...

  8. 深入解析spring中用到的九种设计模式

    转载请注明出处,文章首发于:http://itxxz.com/a/javashili/tuozhan/2014/0601/7.html 设计模式作为工作学习中的枕边书,却时常处于勤说不用的尴尬境地,也 ...

  9. UML九种图 之 包图和对象图

    前言     对象图和包图依然是对系统的静态的描写叙述.UML九种图加上包图,事实上是十幅图. 包图     1.构成           2.包中的元素      类.接口.用例.构件.其他包等.( ...

随机推荐

  1. pixel的Edxposed刷机过程

    1.先解开bl锁 这里的步骤,因为我机子本来就是解过的了,所以简单记录一下过程好了 第一步:确保你的环境变量是否设置好了,判断的标准就是打开终端(我是mac),usb连接上,然后输入 adb devi ...

  2. Linux 3.16 release 贡献度

    内核 3.16 release 的贡献度可以在下面网页看到: http://www.remword.com/kps_result/3.16_whole.html 一共发布了 12802 个补丁, 18 ...

  3. NodeJS 进程是如何退出的

    有几种因素可以导致 NodeJS 进程退出.在这些因素中,有些是可预防的,比如代码抛出了一个异常:有些是不可预防的,比如内存耗尽.process 这个全局变量是一个 Event Emitter 实例, ...

  4. Linux | 文本编辑器vim

    vim 编辑器介绍 vim 编辑器是一款非常棒的文本处理工具,它会默认安装在当前所有的 Linux 操作系统上面. vim 编辑器中设置了三种模式,可以极大的提高我们的工作效率: 命令模式:控制光标移 ...

  5. C语言变量 类型判断

    变量三要素: 一个变量有三个基本的要素,变量的名称,变量的类型,变量的值.所以int a = 10; 变量名为a,变量的存储类型为int型,变量的值为10. 变量还有一些属性如作用范围和存储类型. 变 ...

  6. datax的安装和使用(windows)

    github官方文档和项目:https://github.com/alibaba/DataX 下载后在windows环境下是可以直接用python编译执行的,但从github上下载的版本只支持pyth ...

  7. 手写系列-实现一个铂金段位的 React

    一.前言 本文基于 https://pomb.us/build-your-own-react/ 实现简单版 React. 本文学习思路来自 卡颂-b站-React源码,你在第几层. 模拟的版本为 Re ...

  8. HTML5-CSS(三)

    一.CSS  盒模型 1.元素尺寸:CSS 盒模型中最基础的就是设置一个元素的尺寸大小.有三组样式来配置一个元素的尺寸大小,样式表如下 //设置元素尺寸 div { width: 200px;heig ...

  9. GC垃圾回收机制详解

    JVM堆相关知识    为什么先说JVM堆?  JVM的堆是Java对象的活动空间,程序中的类的对象从中分配空间,其存储着正在运行着的应用程序用到的所有对象.这些对象的建立方式就是那些new一类的操作 ...

  10. Python3.9安装PySpider步骤及问题解决

    先写一些前言吧,自己感觉python已经有一定的基础了,但是在安装这个过程居然用了一下午,感觉有些收货,特地写下来与大家分享一下. PySpider是一个强大的网络爬虫系统,GitHub地址:http ...