ARM汇编之加载寄存器

举报
冬晨夕阳 发表于 2022/03/30 01:17:36 2022/03/30
【摘要】 ARM汇编 将常数加载到寄存器用 MOV 和 MVN 直接加载用 MOV32 加载用 LDR Rd, =const 加载加载浮点常数 将地址加载到寄存器中ADR 和 ADRL 直接加...

寄存器是CPU的组成部分,是有限存贮容量的高速存贮部件,它们可用来暂存 数据、地址、指令
更多介绍可查看: ARM寄存器


将常数加载到寄存器

只有在执行从内存加载数据时,才能用单个指令将任何 32 位立即数加载到寄存器中。这是因为 ARM 和 Thumb-2 指令的长度仅是 32 位。在使用 16 位 Thumb 指令时,可生成的常数范围要小得多。

可以用一次数据加载来将任何 32 位值加载到寄存器中,但也可以使用其他方式来加载许多常用的常数。

Arm指令中,操作码(opcode)、目的操作数(Rd)、源操作数1(Rn)是必须的字段。
条件码(cond)、符号位标记(s)源操作数2(oprand2)是可选的。
其中Rd和Rn必须是寄存器,因此Arm的“立即数”只能存储在oprand2。 Arm指令中的“立即数”是常数表达式。

用 MOV 和 MVN 直接加载

在高版本中,可以先后用 MOV 和 MOVT 这两个指令将任何 32 位值加载到寄存器中。

MOV : 传送一个32位数到寄存器
MON : 把一个32位数的逻辑“非”送到寄存器
MVN : 传送取反的值

  • 16 位Thumb MOV 指令可以加载位于范围 0 到 255 内的任何常数。不能使用 16 位 MVN 指令加载常数。
  • 在 ARM 状态下,在范围 0x0-0xFF (0-255) 内,MOV 可加载任何 8 位常数值。MVN 可加载这些值的按位补码

用 MOV32 加载

在 ARMv6 中,ARM 和 Thumb-2 指令集均包含:

• MOV 指令,它可以将位于范围 0x00000000 到 0x0000FFFF 内的任何值加载到寄存器中

• MOVT 指令,它可将位于范围 0x0000 到 0xFFFF 内的任何值加载到寄存器的最高有效半部。
可使用这两个指令在寄存器中构造任何 32 位常数。也可使用 MOV32 伪指令。

用 LDR Rd, =const 加载

LDR : 从虚拟地址取一个单个的32位值
Rd : 目的操作数,寄存器
const : 常量

LDR Rd,=const 伪指令可在单个指令中构造任何 32 位数字常数。使用此伪指令可生成超出 MOV 和 MVN 指令允许范围的常数。
在这里插入图片描述

加载浮点常数

在 NEON 和 VFPv3 指令集内,有一些指令可将有限范围的浮点常数作为立即数加载


将地址加载到寄存器中

通常需要将地址加到寄存器中。可能需要加载变量、字符串常数或跳转表的起 始位置的地址。
地址通常表示为相对当前 pc 或其他寄存器的偏移量。

ADR 和 ADRL 直接加载

利用 ADR 指令和 ADRL 伪指令,无需执行数据加载即可生成位于某一范围内的地 址。ADR 和 ADRL 接受程序相对表达式,这是一个带有可选偏移量的标签,其中标签地址是相对于当前 pc 的。

用于 ADR 或 ADRL 的标签必须位于同一代码节中
在 Thumb 状态下,16 位 ADR 指令只能生成字对齐的地址。
在没有 Thumb-2 的处理器上的 Thumb 状态下,ADRL 将不可用

用 ADR 加载跳转表地址

在程序中常常需要根据一定的参数选择执行不同的子程序。
跳转表中存放的是各子函数的地址,选择不同的子程序的参数是该子程序在跳转表中的偏移量。
在这里插入图片描述
在这里插入图片描述

跳转表通过下列指令和汇编程序指令来执行:
EQU 是一个汇编程序指令,用于为某一符号赋值。
DCD 声明一个或多个存储字。
LDR LDR pc,[r3,r0,LSL#2] 指令将跳转表所需子句的地址加载到 pc 中,

用 LDR Rd, =label 加载地址

LDR Rd,= :该伪指令可将任何 32 位常数加载到寄存器中,此外它还接受程序相对表达式,如标签以及带偏移量的标签。
汇编程序通过下列方式转换 LDR r0, =label 伪指令:

  • 将 label 的地址放入文字池(在代码中嵌入的一部分内存,用于存放常数值)
  • 生成程序相对的 LDR 指令,以便从文字池读取该地址

用一个字符串覆盖另一个字符串的 ARM 代码例程:
DCB 指令定义一个或多个存储字节
LDR 和 STR 指令使用后变址寻址来更新其地址寄存器
在这里插入图片描述

加载和存储多个寄存器指令

ARM、Thumb 和 Thumb-2 指令集包含用于从内存加载和在内存中存储多个寄存器的指令。

下列指令都可在 ARM 和 Thumb 指令集内使用:

  • LDM 加载多个寄存器。
  • STM 存储多个寄存器。
  • PUSH 将多个寄存器存储到堆栈中并更新堆栈指针。
  • POP 从堆栈中加载多个寄存器,并更新堆栈指针。

加载和存储多个指令可以更新基址寄存器。对于堆栈操作来说,基址寄存器通 常是堆栈指针 R13。这就意味着,可以在单个指令中使用这些指令对任何数量的 寄存器执行推入和弹出操作。


LDR 补充:

以下部分转发于: https://www.jianshu.com/p/66d801c85ee9

LDR指令的格式:

LDR {条件} 目的寄存器 <存储器地址>

作用:将存储器地址所指地址处连续的4个字节(1个字)的数据传送到目的寄存器中。

LDR指令寻址方式实例:
LDR R0,[R1] ;将存储器地址为R1的字数据读入寄存器R0。
LDR R0,[R1,R2] ;将存储器地址为R1+R2的字数据读入寄存器R0。
LDR R0,[R1,#8] ;将存储器地址为R1+8的字数据读入寄存器R0。
LDR R0,[R1],R2 ;将存储器地址为R1的字数据读入寄存器R0,然后R1=R1+8。
LDR R0,[R1],#8 ;将存储器地址为R1的字数据读入寄存器R0,并将R1+8的值存入R1。
LDR R0,[R1,R2]! ;将存储器地址为R1+R2的字数据读入寄存器R0,并将R1+R2的值存入R1。
LDR R0,[R1,LSL #3] ;将存储器地址为R18的字数据读入寄存器R0。
LDR R0,[R1,R2,LSL #2] ;将存储器地址为R1+R24的字数据读入寄存器R0。
LDR R0,[R1,R2,LSL #2]! ;将存储器地址为R1+R24的字数据读入寄存器R0,并将R1+R24的值存入R1。
LDR R0,[R1],R2,LSL #2 ;将存储器地址为R1的字数据读入寄存器R0,并将R1+R2*4的值存入R1。
LDR R0,Label ;Label为程序标号,Label必须是当前指令的-4~4KB范围内。

LDR R,label 和 LDR R,=label的区别

当用 LDR r, =imd // r 为寄存器, imd为立即数
LDR 是一条伪指令。编译器会根据立即数的大小,决定用 ldr 指令或者是mov或mvn指令。

当imd能用mov或者mvn操作时,就将它翻译成一条mov或mvn指令。当imd大于mov或mvn能够操作的数时,编译器会将imd存在一个内存单元中,然后再用一条ldr指令加载这个内存单元的的值到寄存器中。

LDR r, label 和 LDR r, =label的区别:
LDR r, =label 会把label表示的值加载到寄存器中,而LDR r, label会把label当做地址,把label指向的地址中的值加载到寄存器中。
譬如 label的值是 0x8000, LDR r, =label会将 0x8000加载到寄存器中,而LDR r, label则会将内存0x8000处的值加载到寄存器中。


文章来源: blog.csdn.net,作者:考古学家lx,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/weixin_43582101/article/details/108105804

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。