ARM汇编基础-存储和加载指令

ARM体系平台手册笔记06

存储和加载指令

ARM架构支持两种广泛的指令,从内存加载或存储单个寄存器或一对寄存器的值:
    第一种类型可以加载或存储32位字或8位无符号字节
    第二种类型可以加载或存储16位无符号半字,并可以加载和有符号扩展16位半字或8位字节。
    在ARMv5TE及更高版本中,它还可以加载或存储一对32位字

寻址模式

在两种类型的指令中,寻址模式由两部分组成:
    1、基址寄存器
    2、偏移                        
基址寄存器可以是通用寄存器(包括PC,允许PC相对寻址位置无关代码)中的任何一个。

偏移量采用三种格式之一:
    Immediate 
        偏移量是无符号数,可以从基址寄存器中加或减。立即(数)偏移寻址对于访问与数据对象起始位置固定距离的数据元素(如结构域,堆栈偏移量和输入/输出寄存器)非常有用。对于字和无符号字节指令,立即偏移是12位数。对于半字和有符号的字节指令,它是一个8位数字
    Register
        偏移量是通用寄存器(而不是PC),可以从基址寄存器中加或减。寄存器偏移对于访问数组或数据块很有用
    Scaled register
        偏移是通用寄存器(而不是PC)移位立即值,然后添加到或从基址寄存器中减去。可以使用用于数据处理指令的相同的移位操作(逻辑左移,逻辑右移,算术左移和算术右移),但逻辑左移是最有用的,因为它允许索引的数组按照大小的每个数组元素。缩放寄存器偏移仅适用于字和无符号字节指令

除了上述三种偏移之外,偏移和基址寄存器以三种不同的方式来构成内存地址。寻址方式如下:
    Offset 
        添加或减去基址寄存器和偏移量以形成内存地址   
    Pre-indexed 
        添加或减去基址寄存器和偏移量以构成内存地址。
        然后使用此新地址更新基址寄存器,以允许通过数组或内存块进行自动索引       
    Post-indexed
        单独使用基址寄存器的值作为内存地址。基址寄存器和偏移量相加或减去,
        并将该值存储回基址寄存器,以允许通过数组或内存块进行自动索引

存储和加载字或则无符号byte指令

    加载指令从内存加载一个值,并将其写入通用寄存器,存储指令从通用寄存器读取值并将其存储到内存中
指令格式:
    LDR|STR{<cond>} {B}{T} Rd, <addressing_mode>                            
31      28 27 26 25 24 23 22 21 20 19        16 15       12 11                      0
   code    0   1  I  P  U  B  W  L       Rn           Rd       addressing_mode_specific

    I P U W 标志位 是区分不同类型的<address_mode>的位。请参阅寻址模式2 - 载入和存储字或无符号字节在第A5-18页
    L 位 用来区分加载(L == 1)和存储指令(L == 0)
    B 位 区分无符号字节(B == 1)和字(B == 0)访问。
    Rn 通过<address_mode>指定使用的基址寄存器

    Rd 指定要加载或存储其内容的寄存器

存储和加载半字或则双字,无符号byte指令

    加载指令从内存加载单个值,并将其写入通用寄存器或一对通用寄存器,存储指令从通用寄存器或一对通用寄存器读取值,并将其存储到内存中
指令格式:
LDR|STR{<cond>} D | H|SH |SB   Rd,<addressing_mode>

31       28 27 26 25 24 23 22 21 20 19       16 15       12 11       8 7 6 5 4 3         0
   cond     0  0  0  P  U   I  W  L     Rn          Rd       addr_mode 1 S H 1   addr_mode

addr_mode 是寻址模式特定的位
I,P,U,W 标志位用来指定寻址模式 (请参见第A5-33页上的寻址模式3 - 杂项加载和存储)
L,S,H 这些位组合指定有符号或无符号加载或存储,以及双字,半字或字节访问。有关详细信息,请参阅第A5-33页的寻址模式3 - 杂项负载和存储。
Rn  指定寻址模式使用的基址寄存器
Rd  指定要加载或存储其内容的寄存器

举例:
    LDR R1,[R0]             ;将R0中的地址内容加载到R1中
    LDR R8,[R3,#4]          ;R8 = [R3 + 4]
    LDR R12, [R13,#-4]      ;R12 = [R13 - 4]
    STR R2,[R1,#0X100]      ;[R1+ 0x100] = R2
    LDRB R5,[R9]            ;从R9加载最低byte值到R5中,高3个byte为0值
    STRB R3,[R8,#3]         ;[R8+ 3] = (unsigned byte)R3
    LDR  R11,[R1,R2]        ;R11 = [R1 + R2]
    STRB R10,[R7,-R4]       ;[R7-R4] = (unsigned byte)R10
    LDR R11,[R3,R5,LSL #2]  ; R11 = [R3 + R5 * 4]

    LDR  R1,[R0,#4]!        ;R1 = [R0 + 4],R0 = R0 + 4     (! 有点++i味道)
    STRB R7,[R6,#-1]!       ;[R6 -1] = R7; R6 = R6 - 1;  

    LDR  R3,[R9],#4         ; R3 = [R9],R9 = R9 + 4   这指令很有魅惑性(有点i++味道)
    STR  R2,[R5],#8         ; [R5] = R2,R5 = R5 + 8;
    LDRH R1,[R0]            ;R1 = (unsigned short)[R0]
    LDRH R12,[R13, #-6]     ;R12 = (unsigned short)[R13 - 6]
    STRH R2,[R1,#0X80]      ;[R1+ 0X80] = (short)R2
    LDRSH R5,[R9]           ;R5 = (short)[R9],加载有符号半字
    LDRSB R3,[R8,#3]        ;R3 = (byte)[R8 + 3]
    LDRSB R4,[R10,#0xC1]    ;R4 = (byte)[R10 + 0xC1]
    LDRH  R11,[R1,R2]       ;R11 = (unsigned short)[R1 + R2]
    STRH  R10,[R7,-R4]      ;[R7 - R4] = (unsigned short)R10

    LDRSH R1,[R0,#2]!       ;R1 = (short)[R0 + 2];R0 = R0 + 2;
    LDRSB R7,[R6,#-1]!      ;[R6 - 1] = (byte)R7,R6 = R6 - 1;
    LDRH  R3,[R9],#2        ; R3 = (unsigned short)[R9],R9 = R9 + 2;
    STRH  R2,[R5],#8        ;[R5] = (unsigned short)R2, R5 = R5 + 8;

    LDRD R4,[R9]            ;R4 = [R9],R5 = [R9 + 4]    多寄存器操作
    STRD  R8,[R2 #0X2C]     ;[R2+ 0X2C] = R8 
                            ;[R2 + 0X2C + 4] = R9
指令列表:
    LDR     load word
    LDRB    load byte
    LDRBT    load byte with user mode Privilege
    LDRD    load DoubleWord
    LDREX   load exclusive
    LDRH     load unsigned half word
    LDRSH    load signed half word
    LDRSB    load signed byte
    LDRT     load word with user mode Privilege
    STR指令跟上述LDR指令描述一致

加载和存储多个指令

加载多个指令从存储器加载通用寄存器的子集,或可能全部加载
存储多个指令将通用寄存器的子集或可能全部存储到存储器中
指令格式:
    LDM{<cond>}<addressing_mode> Rn{!},<registers>{^}
    STM{<cond>}<addressing_mode> Rn{!},<registers>{^}

条件:
    <addressing_mode>  = IA |IB | DA| DB | FD | FA| ED |EA

31      28 27 26 25 24 23 22 21 20 19        16 15                   0
   cond    1  0  0   P  U  S  W  L      Rn         register list

    register list 每个通用寄存器的<register>列表有一位。位0用于R0,位15用于R15(PC)。寄存器语法列表是一个开头括号,后面是逗号分隔的寄存器列表,后跟一个关闭括号。可以通过将范围中的第一个和最后一个寄存器与负号分开来指定一系列连续寄存器
    P,U,W 标志位  这些位区分不同类型的寻址模式
    S 位  对于加载PC的LDM,S位表示在所有寄存器加载后,从SPSR加载CPSR。对于没有加载PC的所有STM和LDM,它表示当处理器处于特权模式时,
        用户模式存储的寄存器被传送,而不是当前模式的寄存器 
    L位 区分是加载,还是存储指令
    Rn   这指定了寻址模式使用的基址寄存器

例子:
    STMFD R13!,{R0 - R12,LR}    ;
        //参考[R13] = R0,[R13 + 4] = R1....[R13 + 13*4] = LR
    LDMFD R13!,{R0 - R12 ,PC}
        //伪代码:  for i = 0 to 14
                if register_list[i] == 1 then
                    Ri = Memory[address,4]
                    address = address + 4
        //参考:R0 = [R13],R1 = [R13 + 4].... PC = [R13 + 13*4]
    LDMIA R0 ,{R5,- R8}
    STMDA R1!,{R2,R5,R7 - R9,R11}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值