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

1.1 LDR和STR(直接偏移量)

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

语法

op{type}{cond} Rt, [Rn {, #offset}]       ;立即偏移
op{type}{cond} Rt, [Rn, #offset]!        ;前索引
op{type}{cond} Rt, [Rn], #offset        ;后索引

op{type}{cond} Rt, Rt2, [Rn {, #offset}]       ;双字立即偏移
op{type}{cond} Rt, Rt2, [Rn, #offset]!        ;双字前索引
op{type}{cond} Rt, Rt2, [Rn], #offset        ;双字后索引

其中: 
op 是下列项之一: 
  LDR     加载寄存器。 
  STR     存储寄存器。 
type 是下列项之一: 
  B      无符号字节(加载时零扩展为 32 位。) 
  SB     有符号字节(仅 LDR。符号扩展为 32 位。) 
  H      无符号半字(加载时零扩展为 32 位。) 
  SH     有符号半字(仅 LDR。符号扩展为 32 位。) 
  -      如果是字,则省略。 
cond 是一个可选的条件代码(请参阅条件执行)。 
Rt         要加载或存储的寄存器。 
Rn         内存地址所基于的寄存器。 
offset     是偏移量。如果省略了 offset,则该地址为 Rn 中的地址。 
Rt2        为附加寄存器,在双字运算中使用,用于加载或存储。

实例

;实例                功能描述
; ldr: load register
.equ    label,    0x80002000
ldr    r0,    label            ;从地址label读取一个字到r0
ldr    r0,    =label            ;把label这个“立即数”加载到r0
ldr    r1,    r0                ;从地址r0读取数据到r1中
ldr    r2,    [r0, #offset]    ;从地址r0+offset处读取一个字到r2
ldrb    r2,    [r0, #offset]    ;从地址r0+offset处读取一个字节到r2
ldrh    r2,    [r0, #offset]    ;从地址r0+offset处读取一个半字到r2
LDRD    r0,    r1,    [r2, #offset]    ;从地址r2+offset处读取双字(64位)到
                                        ;r0(低32位)和r1(高32位)
                                        
;前索引
ldr    r1,    [r0, #offset]!    ;从地址r0+offset处读取一个字到r1,然后r0=r0+offset
                                    ;如果没有! 那么最后r0的值得不到更新
ldrd    r1, r2, [r0, #offset]!  ;从r0+offset地址读取64位数据到r1(低32位)和r2(高32位)
                                ;然后r0=r0+offset
;后索引                                    
ldr    r1,    [r0], #offset      ;从r0地址获取一个字加载到r1,然后r0=r0+offset 
ldrd r1, r2, [r0], #offset      ;从r0地址获取一个双字加载到r1, r2,然后r0=r0+offset                                 

; str store register
str    r0,    label            ;从r0读取一个字到地址label中
str    r0,    =label            ;把r0值更新label这个“立即数”
str    r1,    r0                ;从地址r1读取数据到r0中
str    r2,    [r0, #offset]     ;从地址r2处读取一个字到r0+offset
strb    r2,    [r0, #offset]    ;从地址r2处读取一个低字节到r0+offset
strh    r2,    [r0, #offset]    ;从地址r2处读取一个低半字到r0+offset
STRD    r0,    r1,    [r2, #offset]    ;从地址r0(低32位)和r1(高32位)处
                                        ;读取双字到r2+offset
                                        
;前索引
str    r1,    [r0, #offset]!    ;从地址r1处读取一个字到r0+offset,然后r0=r0+offset
                                    ;如果没有! 那么最后r0的值得不到更新
strd    r1, r2, [r0, #offset]!  ;从r1(低32位)和r2(高32位)地址读取64位数据到r0+offset
                                ;然后r0=r0+offset
;后索引                                    
str    r1,    [r0], #offset      ;从r1地址获取一个字加载到r0,然后r0=r0+offset 
strd r1, r2, [r0], #offset      ;从r1, r2地址获取一个双字加载到r0,然后r0=r0+offset   

1.2 LDM和STM

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

语法

op{addr_mode}{cond} Rn{!}, reglist{^}

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

实例


ldmia    sp!, {r0-r12,lr}    ;1.加载sp数据到lr, 然后sp=sp+4; 2.加载sp数据到r12, 然后sp=sp+1;
                                ; 以此类推,最后加载sp数据到r0,然后sp=sp+1
                                ; Rn为sp时,等效于POP
ldmib    sp!, {r0-r12,lr}    ;1.先sp=sp+4,然后加载sp数据到lr; 2.先sp=sp+1, 然后加载sp数据到r12;
                                ; 以此类推,最后,先sp=sp+1,然后加载sp数据到r0
ldmda    sp!, {r0-r12,lr}    ;先传输后sp增后                ;
ldmdb    sp!, {r0-r12,lr}    ;sp先自增后传输

stmia    sp!, {r0-r12,lr}    ;1.存储lr数据到sp,然后sp=sp+4; 2.存储r12数据到sp,然后sp=sp+1;
                             ; 以此类推,最后 存储r0数据到sp,然后sp=sp+4
                             ; Rn为sp时,等效于PUSH
stmib    sp!, {r0-r12,lr}    ;sp先自增后传输
stmda    sp!, {r0-r12,lr}    ;sp先传输后自减
stmdb    sp!, {r0-r12,lr}    ;sp先自减后传输

ldmia    sp, {r0-r12,lr}    ; sp 不带!时,传输完成后,sp地址不变

你可能感兴趣的:(汇编攻城记,汇编,assembly)