• 汇编攻城记-LDR/STR/LDM/STM数据传输


    1.1 LDR和STR(直接偏移量

    带有直接偏移量、前变直接偏移量或后边直接偏移量的加载和存储。

    语法

    1. op{type}{cond} Rt, [Rn {, #offset}] ;立即偏移
    2. op{type}{cond} Rt, [Rn, #offset]! ;前索引
    3. op{type}{cond} Rt, [Rn], #offset ;后索引
    4. op{type}{cond} Rt, Rt2, [Rn {, #offset}] ;双字立即偏移
    5. op{type}{cond} Rt, Rt2, [Rn, #offset]! ;双字前索引
    6. op{type}{cond} Rt, Rt2, [Rn], #offset ;双字后索引
    7. 其中:
    8. op 是下列项之一:
    9. LDR 加载寄存器。
    10. STR 存储寄存器。
    11. type 是下列项之一:
    12. B 无符号字节(加载时零扩展为 32 位。)
    13. SB 有符号字节(仅 LDR。符号扩展为 32 位。)
    14. H 无符号半字(加载时零扩展为 32 位。)
    15. SH 有符号半字(仅 LDR。符号扩展为 32 位。)
    16. - 如果是字,则省略。
    17. cond 是一个可选的条件代码(请参阅条件执行)。
    18. Rt 要加载或存储的寄存器。
    19. Rn 内存地址所基于的寄存器。
    20. offset 是偏移量。如果省略了 offset,则该地址为 Rn 中的地址。
    21. Rt2 为附加寄存器,在双字运算中使用,用于加载或存储。

    实例

    1. ;实例 功能描述
    2. ; ldr: load register
    3. .equ label, 0x80002000
    4. ldr r0, label ;从地址label读取一个字到r0
    5. ldr r0, =label ;把label这个“立即数”加载到r0
    6. ldr r1, r0 ;从地址r0读取数据到r1中
    7. ldr r2, [r0, #offset] ;从地址r0+offset处读取一个字到r2
    8. ldrb r2, [r0, #offset] ;从地址r0+offset处读取一个字节到r2
    9. ldrh r2, [r0, #offset] ;从地址r0+offset处读取一个半字到r2
    10. LDRD r0, r1, [r2, #offset] ;从地址r2+offset处读取双字(64位)到
    11. ;r0(低32位)和r1(高32位)
    12. ;前索引
    13. ldr r1, [r0, #offset]! ;从地址r0+offset处读取一个字到r1,然后r0=r0+offset
    14. ;如果没有! 那么最后r0的值得不到更新
    15. ldrd r1, r2, [r0, #offset]! ;从r0+offset地址读取64位数据到r1(低32位)和r2(高32位)
    16. ;然后r0=r0+offset
    17. ;后索引
    18. ldr r1, [r0], #offset ;从r0地址获取一个字加载到r1,然后r0=r0+offset
    19. ldrd r1, r2, [r0], #offset ;从r0地址获取一个双字加载到r1, r2,然后r0=r0+offset
    20. ; str store register
    21. str r0, label ;从r0读取一个字到地址label中
    22. str r0, =label ;把r0值更新label这个“立即数”
    23. str r1, r0 ;从地址r1读取数据到r0中
    24. str r2, [r0, #offset] ;从地址r2处读取一个字到r0+offset
    25. strb r2, [r0, #offset] ;从地址r2处读取一个低字节到r0+offset
    26. strh r2, [r0, #offset] ;从地址r2处读取一个低半字到r0+offset
    27. STRD r0, r1, [r2, #offset] ;从地址r0(低32位)和r1(高32位)处
    28. ;读取双字到r2+offset
    29. ;前索引
    30. str r1, [r0, #offset]! ;从地址r1处读取一个字到r0+offset,然后r0=r0+offset
    31. ;如果没有! 那么最后r0的值得不到更新
    32. strd r1, r2, [r0, #offset]! ;从r1(低32位)和r2(高32位)地址读取64位数据到r0+offset
    33. ;然后r0=r0+offset
    34. ;后索引
    35. str r1, [r0], #offset ;从r1地址获取一个字加载到r0,然后r0=r0+offset
    36. strd r1, r2, [r0], #offset ;从r1, r2地址获取一个双字加载到r0,然后r0=r0+offset

    1.2 LDM和STM

    加载、存储多个寄存器,可以使用r0-r15任何寄存器组合进行传输。

    语法

    1. op{addr_mode}{cond} Rn{!}, reglist{^}
    2. 其中:
    3. op 指令
    4. LDM load multiple registers 加载多个寄存器
    5. STM store multiple registers 存储多个寄存器
    6. addr_mode 模式
    7. IA increment address after each transfer 先传输后地址自增
    8. IB increment address before each transfer 先地址自增后传输
    9. DA decrement address after each transfer 先传输后地址自减
    10. DB decrement address before each transfer 先地址自减后传输
    11. FD full descending stack 满栈递增,地址从当前sp开始
    12. ED empty descending stack 空栈递增,地址从sp+4开始取数据
    13. FA full ascending stack 满栈递减
    14. EA empty ascending stack. 空栈递减
    15. cond 是一个可选的条件代码(请参阅第2-17 页的条件执行)。
    16. Rn 是基址寄存器,存储有用于传送初始地址的 ARM 寄存器。Rn 不能 为 r15。
    17. ! 是一个可选的后缀。如果有 ! ,则最终地址将写回到 Rn 中。
    18. reglist 是一个或多个要加载或存储的寄存器列表,括在大括号内。
    19. 可包含 寄存器范围。如果包含多个寄存器或寄存器范围,
    20. 则必须用逗号隔 开(请参阅第4-28 页的示例)。
    21. 请参阅第4-27 页的32 位 Thumb-2 指令中的 reglist 限制。
    22. ^ 为一个可选后缀,仅可用于 ARM 状态。不可在用户模式或系统模 式下使用。

    实例

    1. ldmia sp!, {r0-r12,lr} ;1.加载sp数据到lr, 然后sp=sp+4; 2.加载sp数据到r12, 然后sp=sp+1;
    2. ; 以此类推,最后加载sp数据到r0,然后sp=sp+1
    3. ; Rn为sp时,等效于POP
    4. ldmib sp!, {r0-r12,lr} ;1.先sp=sp+4,然后加载sp数据到lr; 2.先sp=sp+1, 然后加载sp数据到r12;
    5. ; 以此类推,最后,先sp=sp+1,然后加载sp数据到r0
    6. ldmda sp!, {r0-r12,lr} ;先传输后sp增后 ;
    7. ldmdb sp!, {r0-r12,lr} ;sp先自增后传输
    8. stmia sp!, {r0-r12,lr} ;1.存储lr数据到sp,然后sp=sp+4; 2.存储r12数据到sp,然后sp=sp+1;
    9. ; 以此类推,最后 存储r0数据到sp,然后sp=sp+4
    10. ; Rn为sp时,等效于PUSH
    11. stmib sp!, {r0-r12,lr} ;sp先自增后传输
    12. stmda sp!, {r0-r12,lr} ;sp先传输后自减
    13. stmdb sp!, {r0-r12,lr} ;sp先自减后传输
    14. ldmia sp, {r0-r12,lr} ; sp 不带!时,传输完成后,sp地址不变

  • 相关阅读:
    在Mac电脑下怎么部署QAnything?
    用VS开发一款“飞机大战“单机游戏<C++>
    Redis数据序列化器
    while 与 for
    WSL(ubuntu) 和Cisco Anyconnect存在的网络连接异常问题
    【Linux】文件系统中inode与软硬链接以及读写权限问题
    【elementUI】el-dropdown相关
    SpringCloud系列(三)Nacos 注册中心的搭建及服务发现
    C++知识精讲15 | 三类基于贪心思想的区间覆盖问题【配套资源详解】
    jquery实现select多选框的左右移动
  • 原文地址:https://blog.csdn.net/nawei87/article/details/132639562