ARM寻址方式

2023-10-31

所谓寻址方式就是处理器根据指令中给出的地址信息来寻找物理地址的方式

ARM处理器的寻址方式

目前ARM处理器支持9种寻址方式,分别是立即数寻址寄存器寻址寄存器偏移寻址寄存器间接寻址基址变址寻址多寄存器寻址相对寻址堆栈寻址块拷贝寻址

1. 立即数寻址

也叫立即寻址,是一种特殊的寻址方式,操作数本身包含在指令中,只要取出指令也就取到了操作数。这个操作数叫做立即数,对应的寻址方式叫做立即寻址。例如:

MOV R0,#64     ;R0  ← 64

ADD R0, R0, #1  ;  R0   ← R0 + 1

SUB R0, R0, #0X3D  ;  R0   ← R0 – 0X3D

在立即数寻址中,要求立即数以“#”为前缀对于以十六进制表示的立即数,还要求在“#”后加上“0X”或“&”或”0x“。

在ARM处理器中,立即数必须对应8位位图格式,即立即数是一个在16位或32位的寄存器中的8bit常数,经循环移动偶数位得到。合法的立即数必须能够找到得到它的那个常数,否则这个立即数就是非法的。

例如:0X80是合法的,它可以通过0X80向左或向右移动0位得到,由于8位的常数都可以由其自身移动0位得到,因此8位的立即数都是合法的

0X03F8也是合法的,把它写成二进制形式为:0011 1111 1000,可以看出如果使用0XFE这个8位的常数在16位寄存器中循环左移2位就可以得到0X03F8。

判断一个立即数是否合法可以用以下的办法:即对于这个立即数进行循左移或右移操作,看看经过移动偶数位后,是否可以得到一个不大于0XFF的立即数(即不超过8位的立即数),如果可以得到,这个立即数就是合法的,否则就是非法的。象0X1010、0X1FA、0X1FF都是不合法的。

2. 寄存器寻址

寄存器寻址就是利用寄存器中的数值作为操作数,也称为寄存器直接寻址

例如:ADD R0,R1, R2         ;R0  ← R1 + R2

该指令的执行效果是将寄存器R1和R2的内容相加,其结果存放在寄存器R0中。

这种寻址方式是各类微处理器经常采用的一种方式,也是执行效率较高的寻址方式。

3. 寄存器间接寻址

寄存器间接寻址就是把寄存器中的值作为地址,再通过这个地址去取得操作数,操作数本身存放在存储器(内存)中

寄存器用中括号[]括起来。

例如:

LDR R0,[R1]

;R0 ←[R1],以寄存器R1的值作为操作数的地址,把取得操作数传送到R0中

ADD R0,R1,[R2]

;R0 ←R1 + [R2],以寄存器R2的值作为操作数的地址,取得操作数后与R1相加,结果存入寄存器R0中。

4. 寄存器偏移寻址

这是ARM指令集特有的寻址方式,它是在寄存器寻址得到操作数后再进行移位操作,得到最终的操作数。

例如:

MOV R0,R2,LSL  #3   ;R0 ← R2 * 8 ,R2的值左移3位,结果赋给R0。

MOV R0,R2,LSL  R1 ;R2的值左移R1位,结果放入R0。

可采用的移位操作如下:

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的值来填充,低端移出的位填入进位标志位。

5. 寄存器基址变址寻址

寄存器基址变址寻址又称为基址变址寻址,它是在寄存器间接寻址的基础上扩展来的。它将寄存器(该寄存器一般称作基址寄存器)中的值与指令中给出的地址偏移量相加,从而得到一个地址,通过这个地址取得存储器(内存)中的操作数

例如:

LDR R0,[R1,#4]

;R0 ←[R1 + 4],将R1的内容加上4形成操作数的地址,取得的操作数存入寄存器R0中。

LDR R0,[R1,#4]

;R0 ←[R1 + 4]、R1 ←R1 + 4,将R1的内容加上4形成操作数的地址,取得的操作数存入寄存器R0中,然后,R1的内容自增4个字节。

其中感叹号!表示指令执行完毕把最后的数据地址写到R1

LDR R0,[R1,R2]

;R0 ←[R1 + R2],将寄存器R1的内容加上寄存器R2的内容形成操作数的地址,取得的操作数存入寄存器R0中。

STR R0, [R1,#-4]

;R0→[R1 -4],将R1中的数值减4作为地址,把R0中的数据存放到这个地址中。

LDR R0,[R1],#4    

;R0 ←[R1]、R1 ←R1+4

 

6. 多寄存器寻址

这种寻址方式可以一次完成多个寄存器值的传送。用花括号{}括起来。

例如:

LDMIA  R0,{R1,R2,R3,R4}

LDM:Load Data from Memory to Register.

;R1←[R0],R2←[R0+4],R3←[R0+8],R4←[R0+12]

该指令的后缀IA表示在每次执行完加载/存储操作后,R0按字长度增加,因此,指令可将连续存储单元的值传送到R1~R4。

LDMIA  R0,{R1-R4}  ;功能同上。

使用多寄存器寻址指令时,寄存器子集的顺序如果由小到大的顺序排列,可以使用“-”连接,否则,用“,”分隔书写。

7. 相对寻址

相对寻址是一种特殊的基址寻址,特殊性是它把程序计数器PC中的当前值作为基地址,语句中的地址标号作为偏移量,将两者相加之后得到操作数的地址。

BL   NEXT  ;相对寻址,跳转到NEXT处执行。

……

……

NEXT

……

 

8. 堆栈寻址

堆栈是一种数据结构,按先进后出(First In Last Out,FILO)的方式工作,使用堆栈指针(Stack Pointer, SP)指示当前的操作位置,堆栈指针总是指向栈顶。

根据堆栈的生成方式不同,可以把堆栈分为递增堆栈和递减堆栈两种类型。如下图所示:

下面的堆栈是指存于内存中的。

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

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

同时,根据堆栈指针(SP)指向的位置,又可以把堆栈分为满堆栈(Full Stack)和空堆栈(Empty Stack)两种类型。

l  满堆栈(Full Stack):堆栈指针指向最后压入堆栈的数据。满堆栈在向堆栈存放数据时的操作是先移动SP指针,然后存放数据。在从堆栈取数据时,先取出数据,随后移动SP指针。这样保证了SP一直指向有效的数据。

l  空堆栈(Empty Stack):堆栈指针SP指向下一个将要放入数据的空位置。空堆栈在向堆栈存放数据时的操作是先放数据,然后移动SP指针。在从堆栈取数据时,是先移动指针,再取数据。这种操作方式保证了堆栈指针一直指向一个空地址(没有有效数据的地址)。

上述两种堆栈类型的组合,可以得到四种基本的堆栈类型,即:

  • 满递增堆栈(FA):堆栈指针指向最后压入的数据,且由低地址向高地址生长。
  • 满递减堆栈(FD):堆栈指针指向最后压入的数据,且由高地址向低地址生长。
  • 空递增堆栈(EA):堆栈指针指向下一个将要压入数据的地址,且由低地址向高地址生长。
  • 空递减堆栈(ED):堆栈指针指向下一个将要压入数据的地址,且由高地址向低地址生长。

堆栈寻址举例如下:

STMFD  SP,{R1-R7, LR}

STM: Store Data From register to Stack (Memory).

;将R1-R7, LR压入堆栈。满递减堆栈。

LDMED  SP,{R1-R7, LR}

;将堆栈中的数据取回到R1-R7, LR寄存器。空递减堆栈。

 

9. 块拷贝寻址

块拷贝寻址用于寄存器数据的批量复制,它实现从由基址寄存器所指示的一片连续存储器到寄存器列表所指示的多个寄存器传送数据。块拷贝寻址与堆栈寻址有所类似。两者的区别在于:堆栈寻址中数据的存取是面向堆栈的,块拷贝寻址中数据的存取是面向寄存器指向的存储单元的

在块拷贝寻址方式中,基址寄存器传送一个数据后有4种增长方式,即:

  1. IA:每次传送后地址增加4;(Increment After Operating)
  2. IB:每次传送前的地址增加4;(Increment Before Operating)
  3. DA:每次传送后地址减少4;(Decrement After Operating)
  4. DB:每次传送前地址减少4。(Decrement Before Operating)

对于32位的ARM指令,每次地址的增加和减少的单位都是4个字节单位。

例如:

STMIA  R0!,{R1—R7}

;将R1-R7的数据保存到R0指向的存储器中,存储器指针在保存第一个值之后增加4,向上增长。R0作为基址寄存器。

STMIB  R0!,{R1—R7}

;将R1-R7的数据保存到存储器中,存储器指针在保存第一个值之前增加4,向上增长。R0作为基址寄存器。

STMDA  R0!,{R1—R7}

;将R1-R7的数据保存到R0指向的存储器中,存储器指针在保存第一个值之后减少4,向下减少。R0作为基址寄存器。

STMDB  R0!,{R1—R7}

;将R1-R7的数据保存到存储器中,存储器指针在保存第一个值之前减少4,向下减少。R0作为基址寄存器。

 

ARM指令中{!},为可选后缀,若选用该后缀,则当数据传送完毕之后,将最后的地址写入基址寄存器,否则基址寄存器的内容不改变。

基址寄存器不允许为R15,寄存器列表可以为R0~R15的任意组合。

{^}为可选后缀,当指令为LDM且寄存器列表中包含R15,选用该后缀时表示:除了正常的数据传送之外,还将SPSR复制到CPSR。同时,该后缀还表示传入或传出的是用户模式下的寄存器,而不是当前模式下的寄存器。

 

LDMIA  R0,{R1,R2,R3,R4}

与LDM IA  R0,{R1,R2,R3,R4}的区别?

前一条指令,执行完毕之后,R0的值保持不变;后一条指令执行完毕之后,R0的值发生了变化。


http://www.cnblogs.com/laojie4321/archive/2012/04/05/2432957.html


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ARM寻址方式 的相关文章

  • 为什么无符号类型在arm cpu中效率更高?

    我正在阅读手臂手册并提出这个建议 但没有提到原因 为什么无符号类型更快 在 ARMv4 之前 ARM 没有对加载半字和有符号字节的本机支持 要加载有符号的字节 你必须LDRB然后对值进行符号扩展 LSL那就起来吧ASR它回落 这很痛苦所以c
  • 通用 ELF 中的重定位(EM:40)

    我尝试从 Ubuntu 交叉编译到Friendly arm 但出现了奇怪的错误 root kevin VirtualBox home kevin Desktop makef make ARCH arm CROSS COMPILE arm n
  • 如何创建具有自定义外设和内存映射的 QEMU ARM 机器?

    我正在为 Cortex M3 cpu 编写代码 并且正在使用以下命令执行单元测试qemu arm二进制 现在一切都很好 但我想知道我是否能够使用测试整个系统qemu system arm 我的意思是 我想为 qemu 编写自定义 机器 我将
  • arm gcc工具链为arm-elf或arm-none-eabi,有什么区别?

    当您构建 gcc 工具链时 可以将其构建为arm elf 或arm none eabi 但是有什么区别呢 我今天使用 eabi 但这只是因为其他人似乎都这样做 但由于这是一个非常糟糕的论点 因此理解其中的差异真的很高兴 注意 此工具链将为基
  • 将 ZeroMQ 交叉编译为 ARM,以便在 MonoTouch iPhone 应用程序配置设置中使用

    我正在尝试在使用 MonoTouch 用 C 开发的 iPhone 应用程序中使用 ZeroMQ 库 我几乎解决了所有的问题 却在最后一道坎倒下了 我正在使用 ZeroMQ 2 1 10 和 C CLR 绑定 包装器 并在 Mac OS X
  • ARM 9处理器的opencv交叉编译

    我需要为 ARM 9 处理器交叉编译 opencv 我有处理器的工具链 但不知道如何交叉编译 请告诉我为arm板交叉编译的过程 谢谢大家 看这个参考 http www airs com ian configure configure 5 h
  • 如何修改内核DTB文件

    Summary 我目前正在为定制板编译 Linux 内核 内核 模块和 DTB 以及一些定制驱动程序 有时 我会编译内核并意识到 DTB 文件中的兼容性字符串不是自定义驱动程序正在寻找的内容 现在 我可以解决此问题的唯一方法是修改 DTS
  • 警告:可加载部分“my_section”位于 ELF 段之外

    我使用 Cortex R4 的 Arm Compiler v6 9 构建了一个 axf elf 文件 但是 当我使用 Arm MCU Eclipse J link GDB 插件将其加载到目标时 它无法加载我的段的初始化数据 如果我使用 Se
  • 手臂“版本”之间的差异? (仅限 ARMv7)

    基本上我想知道ARMv7l和ARMv7之间的区别hl 我有一个带有armv7l的arm处理器 并且有很多armv7的rpmhl 我完全不知道我必须搜索什么才能获得相关信息 这个 后缀 叫什么 还有其他类型吗 他们的做法有何不同 我假设它指示
  • ARM架构中不同处理器模式下如何使用内核堆栈?

    据我了解 每个进程都有一个用户堆栈和内核堆栈 除此之外 ARM 架构中的每种模式都有一个堆栈 所以我想知道不同的堆栈和堆栈指针在 ARM 模式下如何工作 另外 何时会使用与进程关联的内核堆栈 何时会使用与进程关联的内核堆栈 当您进行系统调用
  • 在嵌入式设备上使用new或malloc引起的段错误[关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions 我正在尝试
  • M1 MacBook Pro 上的 Android Studio 无法使用 ABI armeabi-v7a 模拟系统映像

    我的 M1 Macbook Pro 上的 Android Studio 可以很好地模拟 ABI arm64 v8a 的所有系统映像 API 24 29 30 31 但是 它无法使用 ABI armeabi v7a 运行所有映像 例如 API
  • ARM + gcc:不要使用一大块 .rodata 部分

    我想使用 gcc 编译一个程序 并针对 ARM 处理器进行链接时间优化 当我在没有 LTO 的情况下编译时 系统会被编译 当我启用 LTO 时 使用 flto 我收到以下汇编错误 错误 无效的文字常量 池需要更近 环顾网络 我发现这与我系统
  • 使用 Android NDK 使用 -fsigned-char 进行构建安全吗?

    为了与其他平台保持一致 我需要使用signed char在我正在处理的一些本机代码中 但默认情况下在Android NDK上char类型是unsigned 我尝试明确使用signed char类型 但它生成太多警告differ in sig
  • 了解 ctags 文件格式

    我使用 Exhuberant ctags 来索引我的 c 项目中的所有标签 c project 是 Cortex M7 微控制器的嵌入式软件 结果是一个标签文件 我正在尝试阅读该文件并理解所写的内容 根据我找到的 ctags 和 Exhub
  • 为什么当大小大于 50 时,该程序花费的时间会呈指数级增长?

    所以我正在为类编写一个 ARM 汇编快速排序方法 我对大部分内容都有了解 除了复杂性没有意义 我们将其与我们制作的另一种冒泡排序方法进行比较 它对于具有 1 个参数和 10 个参数的示例表现更好 然而 我什至无法比较 100 个参数测试 因
  • Beaglebone Black 的 U-boot 无法构建 - 目标 CPU 不支持 THUMB 指令

    我正在尝试按照 Chris Simmonds 的 掌握嵌入式 Linux 编程 中的说明为 Beagle Bone Black 构建 u boot 我已经构建了交叉工具链 现在正在尝试使用该工具链构建 Das U boot 但由于不支持 T
  • ARM 系统调用的接口是什么?它在 Linux 内核中的何处定义?

    我读过有关 Linux 中的系统调用的内容 并且到处都给出了有关 x86 架构的描述 0x80中断和SYSENTER 但我无法追踪 ARM 架构中系统调用的文件和进程 任何人都可以帮忙吗 我知道的几个相关文件是 arch arm kerne
  • 交叉编译armv5,但它创建v7二进制文件

    我设法为arm926ej s创建了一个目标文件我在 qemu 上使用 Debian Arm arm linux gnueabi gcc 4 4 static O c mcpu arm926ej s hello c o hello root
  • 英特尔的最后分支记录功能是英特尔处理器独有的吗?

    最后分支记录是指存储与最近执行的分支相关的源地址和目标地址的寄存器对 MSR 的集合 它们受英特尔酷睿 2 英特尔至强和英特尔凌动处理器系列的支持 http css csail mit edu 6 858 2012 readings ia3

随机推荐

  • Segmentation fault (core dumped) 错误的一种解决场景

    错误类型 Segmentation fault core dumped 产生原因 Segmentation fault 段错误 Core Dump 核心转储 是操作系统在进程收到某些信号而终止运行时 将此时进程地址空间的内容以及有关进程状态
  • Springboot+Axios双token解决token过期续签问题

    后端分离使用token进行登录验证时 由于token存在过期时间 每次token过期都需要用户重新登录的话 用户体验很不友好 假如token能跟session一样 如果用户持续在进行操作 就自动延长有效时间 就可以解决问题 但是 token
  • qt利用腾讯云服务器实现不同局域网的通信(tcp)

    网上大多数关于qt通信的文章都是同一局域网通信 这种根本没有达到自己想象中的那种通信的要求 不同局域网的通信 这里用到的方法是客户端发送消息给服务器 然后服务器再发送给另一个局域网的客户 首先我们需要购买一个腾讯云服务器 并在自己电脑登录腾
  • Python记11(网络传输大文件

    客户端 import socket tqdm os 传输数据分隔符 separator
  • log4j2入门(三) PatternLayout输出格式详解

    摘要 本节介绍Log4j的输出格式的详细说明 1 PatternLayout参数 charset 指定字符集 pattern 指定格式 alwaysWriteExceptions 默认为true 输出异常 header 可选项 包含在每个日
  • connect和bind

    UDP 考虑以下情形 我们使用UDP写一个echo程序 客户端模型 while fget sendto recvfrom 如果服务器进程没有启动会如何 通过截包发现服务器响应一个icmp port unreachable 不过这个ICMP错
  • java: javamail 1.6.2 Create Receive Email using jdk 19

    接收邮件 中文是乱码 未解决 param pop3Host pop 163 com param storeType pop3 param user geovindu 163 com param password geovindu autho
  • 安装DevEco Studio 3.0 Beta2

    引言 鸿蒙应用程序前端 北向开发 的开发环境是华为提供的HUAWEI DevEco Studio DevEco Studio支持Windows和macOS系统 本文记录了DevEco Studio 3 0 Beta2在Windows操作系统
  • 学习笔记 JavaScript ES6 NRM源切换

    NRM npm registry manager 镜像源管理工具 两种切换方式 一 终端里输入如下命令即可切换至淘宝镜像源 mac下测试通过 npm config set registry http registry npm taobao
  • krita windows编译源码

    Qt系列文章目录 文章目录 Qt系列文章目录 前言 一 krita 二 krita源码编译 1 Windows下编译 1 编译准备 2 相关命令 使用CMake编译krita 重新编译 使用CMkae bash find package Z
  • 06C++11多线程编程之lock_guard类模板

    06C 11多线程编程之lock guard类模板 1 lock guard概念 1 lock guard是一个类模板 它是mutex的进化版 自动lock 和unlock 类似独占型智能指针unique ptr 是一个保姆 在lock g
  • QT解析XML的三种方式

    1 QT QXmlStreamReader用法小结 解析常用到的函数含义 1 导入一个xml文件或字符串的方式 方式一 QXmlStreamReader reader sXMLContent 字符串的xml 方式二 QXmlStreamRe
  • 自然连接(NATURAL JOIN)

    自然连接 NATURAL JOIN 是一种特殊的等值连接 将表中具有相同名称的列自动进行匹配 1 自然连接不必指定任何连接条件 SQL gt desc emp Name Null Type EMPNO NOT NULL NUMBER 4 E
  • 城市配电网恢复方法

    城市配电网恢复方法是指在大停电事故后 配网与主网断开连接 只能协同利用配网中的分布式电源进行恢复供电的方法 该方法需要考虑多时段 多类型负荷的恢复需求 以及电网 水网 气网的运行约束和发电资源的有限能量约束 计及关键负荷功能恢复需求的多时段
  • 【考研复习:数据结构】查找(不含代码篇)

    前言 1 此篇是基于博主对严蔚敏版教材 数据结构 王道书 数据结构 和在网上相关资料的查询 对第七章 查找 的学习总结 2 查找这一章含代码 C 会写在另一篇 写好后再放链接 3 博主比较喜欢用表格使思路稍微清晰一些 还有一些博主自己怕记乱
  • 找二叉树的中序后继

    设计一个算法 找出二叉搜索树中指定节点的 下一个 节点 也即中序后继 如果指定节点没有对应的 下一个 节点 则返回null 方法一 Definition for a binary tree node public class TreeNod
  • 基于RocketMQ分布式事务 - 完整示例

    前言 之前我们说到 分布式事务是一个复杂的技术问题 没有通用的解决方案 也缺乏简单高效的手段 不过 如果我们的系统不追求强一致性 那么最常用的还是最终一致性方案 今天 我们就基于 RocketMQ来实现消息最终一致性方案的分布式事务 本文代
  • 近期 AI 领域,招聘招生信息汇总

    关注公众号 获取更多AI领域发展机会 本文汇总近期招聘信息 有全职也有实习还有升学机会 有需要的朋友欢迎点击查看详情 投递简历 1 海内外招聘 实习生岗位 同方威视南京研发中心招聘图像算法工程师 北上深 商汤招聘智能视频和数字人算法研究员
  • 初识C语言:一篇文章解决基础的操作符(前置++与后置++的区别)

    目录 一 算术操作符 二 关系操作符 三 赋值操作符 四 自增 自减操作符 前言 总结 前言 1 加法运算符 加法运算符为双目运算符 即应有两个量参与加法运算 右结合性 2 减法运算符 减法运算符为双目运算符 但 也可作负值运算符 此时为单
  • ARM寻址方式

    所谓寻址方式就是处理器根据指令中给出的地址信息来寻找物理地址的方式 ARM处理器的寻址方式 目前ARM处理器支持9种寻址方式 分别是立即数寻址 寄存器寻址 寄存器偏移寻址 寄存器间接寻址 基址变址寻址 多寄存器寻址 相对寻址 堆栈寻址和块拷