前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ARM汇编之加载寄存器

ARM汇编之加载寄存器

作者头像
李玺
发布2021-11-22 14:14:17
1.1K0
发布2021-11-22 14:14:17
举报
文章被收录于专栏:爬虫逆向案例

ARM汇编

代码语言:txt
复制
- [将常数加载到寄存器](https://cloud.tencent.com/developer)
        - [用 MOV 和 MVN 直接加载](https://cloud.tencent.com/developer)
        - [用 MOV32 加载](https://cloud.tencent.com/developer)
        - [用 LDR Rd, =const 加载](https://cloud.tencent.com/developer)
        - [加载浮点常数](https://cloud.tencent.com/developer)
- [将地址加载到寄存器中](https://cloud.tencent.com/developer)
        - [ADR 和 ADRL 直接加载](https://cloud.tencent.com/developer)
        - [用 ADR 加载跳转表地址](https://cloud.tencent.com/developer)
        - [用 LDR Rd, =label 加载地址](https://cloud.tencent.com/developer)
- [加载和存储多个寄存器指令](https://cloud.tencent.com/developer)
- [LDR 补充:](https://cloud.tencent.com/developer)
        - [LDR指令的格式:](https://cloud.tencent.com/developer)
        - [LDR R,label 和 LDR R,=label的区别](https://cloud.tencent.com/developer)

寄存器是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处的值加载到寄存器中。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/08/20 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • ARM汇编
  • 将常数加载到寄存器
    • 用 MOV 和 MVN 直接加载
      • 用 MOV32 加载
        • 用 LDR Rd, =const 加载
          • 加载浮点常数
          • 将地址加载到寄存器中
            • ADR 和 ADRL 直接加载
              • 用 ADR 加载跳转表地址
                • 用 LDR Rd, =label 加载地址
                • 加载和存储多个寄存器指令
                • LDR 补充:
                  • LDR指令的格式:
                    • LDR R,label 和 LDR R,=label的区别
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档