ARM指令集

(备注:汇编中不区分大小写)

CPSR寄存器:
    N、Z、C、V均为条件码标志位。它们的内容可被算术或逻辑运算的结果所改变,并且可以决定某条指令是否被执行。条件码标志各位的具体含义如下表所示:

    标志位  含义
    N       当用两个补码表示的带符号数进行运算时,N=1表示运算的结果为负数;
            N=0表示运算的结果为正数或零

    Z        Z=1表示运算的结果为零,Z=0表示运算的结果非零。

    C        可以有4种方法设置C的值:
            -加法运算(包括CMP):当运算结果产生了进位时(无符号数溢出),C=1,否则C=0。
            -减法运算(包括CMP):当运算时产生了借位时(无符号数溢出),C=0,否则C=1。
            -对于包含移位操作的非加/减运算指令,C为移出值的最后一位。
            -对于其它的非加/减运算指令,C的值通常不会改变。

    V        可以有2种方法设置V的值:
            -对于加减法运算指令,当操作数和运算结果为二进制的补码表示的带符号数时,V=1表示符号位溢出
            -对于其它的非加/减运算指令,V的值通常不会改变。

ARM处理器的指令集可以分为6大指令:
    1.跳转指令
    2.数据处理指令
    3.程序状态寄存器(CPSR)处理指令
    4.加载/存储指令(load/store)
    5.协处理器指令
    6.异常产生指令(软中断)

一、 跳转指令
    跳转指令用于实现程序流程的跳转,在ARM程序中有以下两种方法可以实现程序流程的跳转
        1)使用专门的跳转指令;
        2)直接向程序计数器PC写入跳转地址值,通过向程序计数器PC写入跳转地址值,可以实现
          在4GB的地址空间中的任意跳转,在跳转之前结合使用 (MOV LR,PC) 等类似指令,可以
          保存将来的返回地址值,从而实现在4GB连续的线性地址空间的子程序调用。

    ARM指令集中的跳转指令可以完成从当前指令向前或向后的32MB的地址空间的跳转,包括以下
    4条指令:

    1.B指令
        B指令的格式为:  B{条件} 目标地址

    B指令是最简单的跳转指令。一旦遇到一个B指令,ARM处理器将立即跳转到给定的目标地址,
    从那里继续执行。注意存储在跳转指令中的实际值是相对当前PC值的一个偏移量,而不是一个
    绝对地址,它的值由汇编器来计算(参考寻址方式中的相对寻址)。它是24位有符号数,左移
    两位后有符号再扩展为32位,表示的有效偏移为26位(前后32MB的地址空间)。以下指令:

        B   Label        ;程序无条件跳转到标号Label处执行

        CMP R1,#0       ;当CPSR寄存器中的Z条件码置位时,程序跳转到标号Label处执行
        BEQ Label        
    
    2.BL指令
        BLX指令的格式为:  BL{条件} 目标地址

    BL是另一个跳转指令,但跳转之前,会在寄存器R14中保存PC的当前内容,因此,可以通过将
    R14(LR)的内容重新加载到PC中,来返回到跳转指令之后的那个指令处执行。该指令是实现子
    程序调用的一个基本但常用的手段。

    以下指令:

        BL   Label  ;当程序无条件跳转到标号Label处执行时,同时将当前的PC值保存到
                    ;R14(LR)中

    3.BLX指令
        BLX指令的格式为:   BLX 目标地址

    BLX指令从ARM指令集跳转到指令中所指定的目标地址,并将处理器的工作状态有ARM状态切换
    到Thumb状态,该指令同时将PC的当前内容保存到寄存器R14中。因此,当子程序使用Thumb指
    令集,而调用者使用ARM指令集时,可以通过BLX指令实现子程序的调用和处理器工作状态的切
    换。同时,子程序的返回可以通过将寄存器R14值复制到PC中来完成。

    4.BX指令
        BX指令的格式为:  BX{条件} 目标地址

    BX指令跳转到指令中所指定的目标地址,目标地址处的指令既可以是ARM指令,也可以是
    Thumb指令。

二、数据处理指令
    数据处理指令可分为数据传送指令、算术逻辑运算指令 和比较指令等。
        1)数据传送指令用于在寄存器和存储器之间进行数据的双向传输;
        2)算术逻辑运算指令完成常用的算术与逻辑的运算,该类指令不但将运算结果保存在目的
        寄存器中,同时更新CPSR中的相应条件标志位;
        3)比较指令不保存运算结果,只更新CPSR中相应的条件标志位。
    数据处理指令共以下16条。

    1.MOV指令(传送)
        MOV指令的格式为:  MOV{条件}{S} 目的寄存器,源操作数

    MOV指令可完成从另一个寄存器、被移位的寄存器或将一个立即数加载到目的寄存器。其中S选
    项决定指令的操作是否影响CPSR中条件标志位的值,当没有S时指令不更新CPSR中条件标志位的值。

    指令示例:
        MOV R1,R0            ;将寄存器R0的值传送到寄存器R1
        MOV PC,R14           ;将寄存器R14(LR)的值传送到 PC,常用于子程序返回
        MOV R1,R0,LSL#3     ;将寄存器R0的值左移3位后传送到R1

    2.MVN指令(求反)
        MVN指令的格式为:  MVN{条件}{S} 目的寄存器,源操作数

    MVN指令可完成从另一个寄存器、被移位的寄存器、或将一个立即数加载到目的寄存器。与MOV
    指令不同之处是在传送之前按位被取反了,即把一个被取反的值传送到目的寄存器中。其中S决
    定指令的操作是否影响CPSR中条件标志位的值,当没有S时指令不更新CPSR中条件标志位的值。

    指令示例:
        MVN R0,#0           ;将立即数0取反传送到寄存器R0中,完成后R0=-1

    3.CMP指令(比较)
        CMP指令的格式为:  CMP{条件} 操作数1,操作数2

    CMP指令用于把一个寄存器的内容和另一个寄存器的内容或立即数进行比较,同时更新CPSR中
    条件标志位的值。该指令进行一次减法运算,但不存储结果,只更改条件标志位。标志位表示
    的是操作数1与操作数2的关系(大、小、相等),例如,当操作数1大于操作操作数2,则此后的有GT后缀的指令将可以执行。

    指令示例:
        CMP R1,R0             ;将寄存器R1的值与寄存器R0的值相减,并根据结果设置CPSR的标志位
        CMP R1,#100        ;将寄存器R1的值与立即数100相减,并根据结果设置CPSR的标志位

    重要:
        比较指令:cmp
        结合条件位进行使用,常见条件位:
        eq:比较是否相等
        ne:比较是否不等
        lt:有符号数的小于
        gt:有符号数的大于
        le:有符号数的小于等于
        ge:有符号数的大于等于

        指令示例:
            mov r0, #1
            mov r1, #2
            cmp r0, r1
            subgt r2, r0, r1     ;if(r0 > r1) 则 r2 = r0 - r1
            rsblt r2, r0, r1     ;if(r1 > r0) 则 r2 = r1 - r0  
                                ;这条指令意思就是先判断关系,在做相应运算

    4.CMN指令(负数比较)
        CMN指令的格式为:  CMN{条件} 操作数1,操作数2

    CMN指令用于把一个寄存器的内容和另一个寄存器的内容或立即数取反后进行比较,同时更新
    CPSR中条件标志位的值。该指令实际完成操作数1和操作数2相加,并根据结果更改条件标志位。

    指令示例:
        CMN R1,R0             ;将寄存器R1的值与寄存器R0的值相加,并根据结果设置CPSR 的标志位
        CMN R1,#100          ;将寄存器R1的值与立即数100相加,并根据结果设置CPSR的标志位
        cmn r0, r1           ;cpsr = r1 - r0,但是运算结果只影响CPSR,不保存

    5.TST指令(测试)
        TST指令的格式为:  TST{条件} 操作数1,操作数2

    TST指令用于把一个寄存器的内容和另一个寄存器的内容或立即数进行按位的与运算,并根据
    运算结果更新CPSR中条件标志位的值。操作数1是要测试的数据,而操作数2是一个位掩码,
    该指令一般用来检测是否设置了特定的位。

    指令示例:
        TST R1,#%1        ;用于测试在寄存器R1中是否设置了最低位(%表示二进制数)
        TST R1,#0xffe      ;将寄存器R1的值与立即数0xffe按位与,并根据结果设置CPSR的标志位

    6.TEQ指令(测试相等)
        TEQ指令的格式为:  TEQ{条件} 操作数1,操作数2

    TEQ指令用于把一个寄存器的内容和另一个寄存器的内容或立即数进行按位的异或运算,
    并根据运算结果更新CPSR中条件标志位的值。该指令通常用于比较操作数1和操作数2是否相等。

    指令示例:
        TEQ R1,R2      ;将寄存器R1的值与寄存器R2的值按位异或,并根据结果设置CPSR的标志位

    7.ADD指令(相加)
        ADD指令的格式为:  ADD{条件}{S} 目的寄存器,操作数1,操作数2

    ADD指令用于把两个操作数相加,并将结果存放到目的寄存器中。操作数1应是一个寄存器,
    操作数2可以是一个寄存器,被移位的寄存器,或一个立即数。

    指令示例:
        ADD R0,R1,R2                  ;R0 = R1 + R2
        ADD R0,R1,#256                ;R0 = R1 + 256
        ADD R0,R2,R3,LSL#1             ;R0 = R2 + (R3 << 1)

    8.ADC指令(带进位相加)
        ADC指令的格式为:  ADC{条件}{S} 目的寄存器,操作数1,操作数2

    ADC指令用于把两个操作数相加,再加上CPSR中的C条件标志位的值,并将结果存放到目的
    寄存器中。它使用一个进位标志位,这样就可以做比32位大的数的加法,注意不要忘记设置
    S后缀来更改进位标志。操作数1应是一个寄存器,操作数2可以是一个寄存器,被移位的
    寄存器,或一个立即数。

    以下指令序列完成两个128位数的加法,第一个数由高到低存放在寄存器R7~R4,
    第二个数由高到低存放在寄存器R11~R8,运算结果由高到低存放在寄存器R3~R0:

        ADDS R0,R4,R8          ;加低端的字
        ADCS R1,R5,R9          ;加第二个字,带进位
        ADCS R2,R6,R10         ;加第三个字,带进位
        ADC  R3,R7,R11         ;加第四个字,带进位

    9.SUB指令(相减)
        SUB指令的格式为:  SUB{条件}{S} 目的寄存器,操作数1,操作数2

    SUB指令用于把操作数1减去操作数2,并将结果存放到目的寄存器中。操作数1应是一个寄存器,
    操作数2可以是一个寄存器,被移位的寄存器,或一个立即数。该指令可用于有符号数或
    无符号数的减法运算。

    指令示例:
        SUB R0,R1,R2            ;R0 = R1 - R2
        SUB R0,R1,#256          ;R0 = R1 - 256
        SUB R0,R2,R3,LSL#1      ;R0 = R2 - (R3 << 1)

    10.SBC指令
        SBC指令的格式为:  SBC{条件}{S} 目的寄存器,操作数1,操作数2

    SBC指令用于把操作数1减去操作数2,再减去CPSR中的C条件标志位的反码,并将结果存放到
    目的寄存器中。操作数1应是一个寄存器,操作数2可以是一个寄存器,被移位的寄存器,
    或一个立即数。该指令使用进位标志来表示借位,这样就可以做大于32位的减法,注意不要
    忘记设置S后缀来更改进位标志。该指令可用于有符号数或无符号数的减法运算。

    指令示例:
        SBC R0,R1,R2      ;R0 = R1 - R2 - !C,并根据结果设置CPSR的进位标志位

    11.RSB指令
        RSB指令的格式为:  RSB{条件}{S} 目的寄存器,操作数1,操作数2

    RSB指令称为逆向减法指令,用于把操作数2减去操作数1,并将结果存放到目的寄存器中。
    操作数1应是一个寄存器,操作数2可以是一个寄存器,被移位的寄存器,或一个立即数。
    该指令可用于有符号数或无符号数的减法运算。

    指令示例:
        RSB R0,R1,R2                 ;R0 = R2 – R1
        RSB R0,R1,#256               ;R0 = 256 – R1
        RSB R0,R2,R3,LSL#1           ;R0 = (R3 << 1) - R2

    12.RSC指令(反向带进位减)
        RSC指令的格式为:  RSC{条件}{S} 目的寄存器,操作数1,操作数2

    RSC指令用于把 操作数2减去操作数1,再减去CPSR中的C条件标志位的反码,并将结果存
    放到目的寄存器中。操作数1应是一个寄存器,操作数2可以是一个寄存器,被移位的寄存
    器,或一个立即数。该指令使用进位标志来表示借位,这样就可以做大于32位的减法,
    注意不要忘记设置S后缀来更改进位标志。该指令可用于有符号数或 无符号数的减法运算。

    指令示例:
        RSC R0,R1,R2           ;R0 = R2 – R1 - !C

    13.AND指令(逻辑位 与)
        AND指令的格式为:   AND{条件}{S} 目的寄存器,操作数1,操作数2

    AND指令用于在两个操作数上进行逻辑与运算,并把结果放置到目的寄存器中。操作数1
    应是一个寄存器,操作数2可以是一个寄存器,被移位的寄存器,或一个立即数。该指令
    常用于屏蔽操作数1的某些位。

    指令示例:
        AND R0,R0,#3          ;该指令保持R0的0、1位,其余位清零。
        and r2, r1, r0            ;r2 = r1 & r0,按位与运算,等价于C语言中&

    14.ORR指令(逻辑位 或)
        ORR指令的格式为:  ORR{条件}{S} 目的寄存器,操作数1,操作数2

    ORR指令用于在两个操作数上进行逻辑或运算,并把结果放置到目的寄存器中。操作数1
    应是一个寄存器,操作数2可以是一个寄存器,被移位的寄存器,或一个立即数。该指令
    常用于设置操作数1的某些位。

    指令示例:
        ORR R0,R0,#3         ;该指令设置R0的0、1位,其余位保持不变。
        orr r2, r1, r0           ;r2 = r1 | r0,按位或运算

    15.EOR指令(逻辑位 异或)
        EOR指令的格式为:   EOR{条件}{S} 目的寄存器,操作数1,操作数2

    EOR指令用于在两个操作数上进行逻辑异或运算,并把结果放置到目的寄存器中。操作数1
    应是一个寄存器,操作数2可以是一个寄存器,被移位的寄存器,或一个立即数。该指令
    常用于反转操作数1的某些位。

    指令示例:
        EOR R0,R0,#3        ;该指令反转R0的0、1位,其余位保持不变。
        eor r2, r1, r0          ;r2 = r1 ^ r0,按位异或运算

    16.BIC指令(位清零)
        BIC指令的格式为:  BIC{条件}{S} 目的寄存器,操作数1,操作数2

    BIC指令用于清除操作数1的某些位,并把结果放置到目的寄存器中。操作数1应是一个寄
    存器,操作数2可以是一个寄存器,被移位的寄存器,或一个立即数。操作数2为32位的
    掩码,如果在掩码中设置了某一位,则清除这一位。未设置的掩码位保持不变。

    指令示例:
        BIC R0,R0,#%1011    ;该指令清除R0中的位 0、1、和 3,其余的位保持不变。
        bic r0, #0xf           ; r0 = r0 & ~(0xf<<0),按位清0操作

三、乘法指令与乘加指令
    ARM 微处理器支持的乘法指令与乘加指令共有6条,可分为运算结果为32位和运算结果
    为64位两类,与前面的数据处理指令不同,指令中的所有操作数、目的寄存器 必须为
    通用寄存器,不能对操作数使用立即数或被移位的寄存器,同时,目的寄存器和操作数1
    必须是不同的寄存器。 
    乘法指令与乘加指令共有以下6条:

    1.MUL指令(相乘)
        MUL指令的格式为:  MUL{条件}{S} 目的寄存器,操作数1,操作数2

    MUL指令完成将操作数1与操作数2的乘法运算,并把结果放置到目的寄存器中,同时可以根据
    运算结果设置CPSR中相应的条件标志位。其中,操作数1和操作数2均为32位的有符号数或
    无符号数。

    指令示例:
        MUL  R0,R1,R2           ;R0 = R1 × R2
        MULS R0,R1,R2           ;R0 = R1 × R2,同时设置CPSR中的相关条件标志位

    2.MLA指令(带累加的相乘)
        MLA指令的格式为:  MLA{条件}{S} 目的寄存器,操作数1,操作数2,操作数3

    MLA指令完成将操作数1与操作数2的乘法运算,再将乘积加上操作数3,并把结果放置到目的
    寄存器中,同时可以根据运算结果设置CPSR中相应的条件标志位。其中,操作数1和操作数2
    均为32位的有符号数或无符号数。

    指令示例:
        MLA  R0,R1,R2,R3         ;R0 = R1 × R2 + R3
        MLAS R0,R1,R2,R3         ;R0 = R1 × R2 + R3,同时设置CPSR中的相关条件标志位

    3.SMULL指令
        SMULL指令的格式为:  SMULL{条件}{S} 目的寄存器Low,目的寄存器High,操作数1,操作数2

    SMULL指令完成将操作数1与操作数2的乘法运算,并把结果的低32位放置到目的寄存器Low中,
    结果的高32位放置到目的寄存器High中,同时可以根据运算结果设置CPSR中相应的条件标志
    位。其中,操作数1和操作数2均为32位的有符号数。

    指令示例:
        SMULL R0,R1,R2,R3     ;R0 = (R2 × R3)的低32位
                              ;R1 = (R2 × R3)的高32位

    4.SMLAL指令
        SMLAL指令的格式为:  SMLAL{条件}{S} 目的寄存器Low,目的寄存器High,操作数1,操作数2

    SMLAL指令完成将操作数1与操作数2的乘法运算,并把结果的低32位同目的寄存器Low中的值相加
    后又放置到目的寄存器Low中,结果的高32位同目的寄存器High中的值相加后又放置到目的寄存
    器High中,同时可以根据运算结果设置CPSR中相应的条件标志位。其中,操作数1和操作数2均为
    32位的有符号数。
    对于目的寄存器Low,在指令执行前存放64位加数的低32位,指令执行后存放结果的低32位;
    对于目的寄存器High,在指令执行前存放64位加数的高32位,指令执行后存放结果的高32位。

    指令示例:
        SMLAL R0,R1,R2,R3       ;R0 = (R2 × R3)的低32位 + R0
                                ;R1 = (R2 × R3)的高32位 + R1

    5.UMULL指令
        UMULL指令的格式为:  UMULL{条件}{S}  目的寄存器Low,目的寄存器High,操作数1,操作数2

    UMULL指令完成将操作数1与操作数2的乘法运算,并把结果的低32位放置到目的寄存器Low中,
    结果的高32位放置到目的寄存器High中,同时可以根据运算结果设置CPSR中相应的条件标志位。
    其中,操作数1和操作数2均为32位的无符号数。

    指令示例:
        UMULL R0,R1,R2,R3       ;R0 = (R2 × R3)的低32位
                                ;R1 = (R2 × R3)的高32位

    6.UMLAL指令
        UMLAL指令的格式为:  UMLAL{条件}{S} 目的寄存器Low,目的寄存器High,操作数1,操作数2

    UMLAL指令完成将操作数1与操作数2的乘法运算,并把结果的 低32位同目的寄存器Low中的值
    相加后又放置到目的寄存器Low中,结果的高32位同目的寄存器High中的值相加后又放置到目的
    寄存器High 中,同时可以根据运算结果设置CPSR中相应的条件标志位。其中,操作数1和操作数2
    均为32位的无符号数。
    对于目的寄存器Low,在指令执行前存放64位加数的低32位,指令执行后存放结果的低32位;
    对于目的寄存器High,在指令执行前存放64位加数的高32位,指令执行后存放结果的高32位。

    指令示例:
        UMLAL R0,R1,R2,R3       ;R0 = (R2 × R3)的低32位 + R0
                                ;R1 = (R2 × R3)的高32位 + R1

四、程序状态寄存器(CPSR)访问指令

    1.MRS指令
        MRS指令的格式为:  MRS{条件}  通用寄存器 程序状态寄存器(CPSR或SPSR)

    MRS指令用于将程序状态寄存器的内容传送到通用寄存器中。该指令一般用在以下两种情况:
    Ⅰ.当需要改变程序状态寄存器的内容时,可用MRS将程序状态寄存器的内容读入通用寄存器,
       修改后再写回程序状态寄存器。
    Ⅱ.当在异常处理或进程切换时,需要保存程序状态寄存器的值,可先用该指令读出程序状态
       寄存器的值,然后保存。

    指令示例:
        MRS R0,CPSR                   ;传送CPSR的内容到R0
        MRS R0,SPSR                   ;传送SPSR的内容到R0

    2.MSR指令
        MSR指令的格式为:  MSR{条件}  程序状态寄存器(CPSR或SPSR)_<域>,操作数

    MSR指令用于将操作数的内容传送到程序状态寄存器的特定域中。其中,操作数可以为通用
    寄存器或立即数。
    <域>用于设置程序状态寄存器中需要操作的位,32位的程序状态寄存器可分为4个域:
        位[31:24] 为条件位域,用f表示;
        位[23:16] 为状态位域,用s表示;
        位[15:8] 为扩展位域,用x表示;
        位[7:0] 为控制位域,用c表示;
    该指令通常用于恢复或改变程序状态寄存器的内容,在使用时,一般要在MSR指令中指明将
    要操作的域。

    指令示例:
        MSR CPSR,R0        ;传送R0的内容到CPSR
        MSR SPSR,R0        ;传送R0的内容到SPSR
        MSR CPSR_c,R0      ;传送R0的内容到SPSR,但仅仅修改CPSR中的控制位域

        对CPSR操作流程:先读取旧的值,在针对读的值进行修改,最后回写
            mrs r0, cpsr
            bic r0, #0x1f
            orr r0, #0x10
            msr cpsr, r0

五、加载/存储指令(load/store)
    ARM微处理器支持加载存储指令用于在寄存器和存储器之间传送数据,加载指令用于将存储器
    中的数据传送到寄存器,存储指令则完成相反的操作。常用的加载存储指令如下:

    1.LDR指令
        LDR指令的格式为:  LDR{条件} 目的寄存器,<存储器地址>

    LDR指令用于从存储器中将一个32位的字数据传送到目的寄存器中。该指令通常用于从存储器
    中读取32位的字数据到通用寄存器,然后对数据进行处理。当程序计数器PC作为目的寄存器时,
    指令从存储器中读取的字数据被当作目的地址,从而可以实现程序流程的跳转。该指令在程序
    设计中比较常用,且寻址方式灵活多样,请读者认真掌握。

    指令示例:
        MOV R1, #0x40000004
        LDR R0,[R1]         ;将存储器地址为R1的字数据读入寄存器R0。

        LDR R0,[R1,R2]      ;将存储器地址为R1+R2的字数据读入寄存器R0。
        LDR R0,[R1,#8]      ;将存储器地址为R1+8的字数据读入寄存器R0。
                            ;前索引:在进行读写之前,先调整地址,再将对调整后的地址空间
                            ;进行读写操作

        LDR R0,[R1,R2]!   ;将存储器地址为R1+R2的字数据读入寄存器R0,并将新地址R1+R2写入R1。
        LDR R0,[R1,#8]!  ;将存储器地址为R1+8的字数据读入寄存器R0,并将新地址R1+8写入R1。
                           ;自动索引:先更新地址索引,然后再进行读写操作,最后将更新后的
                           ;地址索引回写到相关寄存器 

        LDR R0,[R1],R2     ;将存储器地址为R1的字数据读入寄存器R0,并将新地址R1+R2写入R1。
                           ;后索引:先进行读写操作,之后再调整地址,并且将新的地址写入
                           ;到相关寄存器

        LDR R0,[R1,R2,LSL#2]!
                    ;将存储器地址为R1+R2×4的字数据读入寄存器R0,并将新地址R1+R2×4写入R1。
        LDR R0,[R1],R2,LSL#2     
                    ;将存储器地址为R1的字数据读入寄存器R0,并将新地址R1+R2×4写入R1。

    2.LDRB指令
        LDRB指令的格式为:  LDR{条件}B 目的寄存器,<存储器地址>

    LDRB指令用于从存储器中将一个8位的字节数据传送到目的寄存器中,同时将寄存器的高24位清零。
    该指令通常用于从存储器中读取8位的字节数据到通用寄存器,然后对数据进行处理。当程序
    计数器PC作为目的寄存器时,指令从存储器中读取的字数据被当作目的地址,从而可以实现程
    序流程的跳转。

    指令示例:
        LDRB R0,[R1]        ;将存储器地址为R1的字节数据读入寄存器R0,并将R0的高24位清零。
        LDRB R0,[R1,#8]    ;将存储器地址为R1+8的字节数据读入寄存器R0,并将R0的高24位清零。

    3.LDRH指令
        LDRH指令的格式为:  LDR{条件}H 目的寄存器,<存储器地址>

    LDRH指令用于从存储器中将一个16位的半字数据传送到目的寄存器中,同时将寄存器的高16
    位清零。该指令通常用于从存储器中读取16位的半字数据到通用寄存器,然后对数据进行处理。
    当程序计数器PC作为目的寄存器时,指令从存储器中读取的字数据被当作目的地址,从而可以
    实现程序流程的跳转。

    指令示例:
        LDRH R0,[R1]       ;将存储器地址为R1的半字数据读入寄存器 R0,并将R0的高16位清零。
        LDRH R0,[R1,#8]   ;将存储器地址为R1+8的半字数据读入寄存器R0,并将R0的高16位清零。
        LDRH R0,[R1,R2]    ;将存储器地址为R1+R2的半字数据读入寄存器R0,并将R0的高16位清零。

    4.STR指令
        STR指令的格式为:  STR{条件} 源寄存器,<存储器地址>

    STR指令用于从源寄存器中将一个32位的字数据传送到存储器中。该指令在程序设计中比较常用,
    且寻址方式灵活多样,使用方式可参考指令LDR。

    指令示例:
        STR R0,[R1],#8    ;将R0中的字数据写入以R1为地址的存储器中,并将新地址R1+8写入R1。
        STR R0,[R1,#8]    ;将R0中的字数据写入以R1+8为地址的存储器中。

    5.STRB指令
        STRB指令的格式为:  STR{条件}B 源寄存器,<存储器地址>

    STRB指令用于从源寄存器中将一个8位的字节数据传送到存储器中。该字节数据为源寄存器中
    的低8位。

    指令示例:
        STRB R0,[R1]        ;将寄存器R0中的字节数据写入以R1为地 址的存储器中。
        STRB R0,[R1,#8]    ;将寄存器R0中的字节数据写入以R1+8为地址的存储器中。

    6.STRH指令
        STRH指令的格式为:  STR{条件}H 源寄存器,<存储器地址>

    STRH指令用于从源寄存器中将一个16位的半字数据传送到存储器中。该半字数据为源寄存器中
    的低16位。

    指令示例:
        STRH R0,[R1]        ;将寄存器R0中的半字数据写入以R1为地址的 存储器中。
        STRH R0,[R1,#8]    ;将寄存器R0中的半字数据写入以R1+8 为地址的存储器中。

六、批量数据加载/存储指令
    ARM微处理器所支持批量数据加载存储指令可以一次在一片连续的存储器单元和多个寄存器
    之间传送数据,批量加载指令用于将一片连续的存储器中的数据传送到多个寄存器,批量数
    据存储指令则完成相反的操作。
    常用的加载存储指令如下:LDM(或STM)指令

    1.LDM(或STM)
        指令的格式为:  LDM(或STM){条件}{类型} 基址寄存器{!},寄存器列表{∧}

    LDM(或STM)指令用于从由基址寄存器所指示的一片连续存储器到寄存器列表所指示的多个
    寄存器之间传送数据,该指令的常见用途是将多个寄存器的内容入栈或出栈。其中,{类型}
    为以下几种情况:

        IA   每次传送后地址加1;(Increase、After)
        IB   每次传送前地址加1;
        DA   每次传送后地址减1;
        DB   每次传送前地址减1;(Dcrease、Befoer)
        FD   满递减堆栈;(FUull、Dcrease)
        ED   空递减堆栈;
        FA   满递增堆栈;
        EA   空递增堆栈;(Empty、Increase)

    {!}为可选后缀,若选用该后缀,则当数据传送完毕之后,将最后的地址写入基址寄存器,否则
    基址寄存器的内容不改变。
    基址寄存器不允许为R15,寄存器列表可以为R0~R15的任意组合。
    {∧}为可选后缀,当指令为LDM且寄存器列表中包含R15,选用该后缀时表示:除了正常的数据
    传送之外,还将SPSR复制到CPSR。同时,该后缀还表示传入或传出的是用户模式下的寄存器,
    而不是当前模式下的寄存器。

    注意:
        1、寄存器列表中的排序和最终于内存之间的对应关系永远是:低编号寄存器对应地地址
        2、当寄存器列表中的寄存器编号连续,可以直接以寄存器区间形式写
        3、需要对地址进行更新时,只要在地址寄存器后边加!
        4、对于一个内存块来说,操作方法有多种:
            d:表示地址递减
            i:表示地址递增
            a:表示after,先读写在更新
            b:表示before,先更新在读写
            stmdb
            stmda
            stmia
            stmib
        5、对于内存块进行写操作和进行读操作
            地址延伸方向相反:以递减方式写入,以递增方式读取
            索引更新相反:写入的时候,在写入之前更新索引(before)的,在读取的时候,
            先读取数据,在更新索引(after)

    指令示例:
        STMFD R13!,{R0,R4-R12,LR}   ;将寄存器列表中的寄存器(R0,R4到R12,LR)存入堆栈。
        LDMFD R13!,{R0,R4-R12,PC}   ;将堆栈内容恢复到寄存器(R0,R4到R12,LR)。
        stmdb r0!, {r1 - r4}
        ldmia r0!, {r5-r8}

七、数据交换指令
    1.SWP指令
        SWP指令的格式为:  SWP{条件} 目的寄存器,源寄存器1,[源寄存器2]

    SWP指令用于将源寄存器2所指向的存储器中的字数据传送到目的寄存器中,同时将源寄存器1
    中的字数据传送到源寄存器2所指向的存储器中。显然,当源寄存器1和目的寄存器为同一个
    寄存器时,指令交换该寄存器和存储器的内容。

    指令示例:
        SWP R0,R1,[R2]
        ;将R2所指向的存储器中的字数据传送到R0,同时将R1中的字数据传送到R2所指向的存储单元。

        SWP R0,R0,[R1]  ;该指令完成将R1所指向的存储器中的字数据与R0中的数据交换。

    2.SWPB指令
        SWPB指令的格式为:  SWP{条件}B 目的寄存器,源寄存器1,[源寄存器2]

    SWPB指令用于将源寄存器2所指向的存储器中的字节数据传送到目的寄存器中,目的寄存器的
    高24清零,同时将源寄存器1中的字节数据传送到源寄存器2所指向的存储器中。显然,当源寄
    存器1和目的寄存器为同一个寄存器时,指令交换该寄存器和存储器的内容。

    指令示例:
        SWPB R0,R1,[R2]     ;将R2所指向的存储器中的字节数据传送到R0,R0的高24位清零,
                            ;同时将R1中的低8位数据传送到R2所指向的存储单元。
        SWPB R0,R0,[R1]     ;该指令完成将R1所指向的存储器中的字节数据与R0中的低8位
                            ;数据交换。

八、移位指令
    对寄存器操作数或内存操作数进行指定位数的移位。可一次移一位,也可一次移位CL规定的次数。
    非循环移位 SHL SHR SAL SAR
    循环移位 ROL ROR RCL RCR

    1.LSL(或ASL)
        LSL(或ASL)的格式为:  通用寄存器,LSL(或ASL) 操作数      

    LSL(或ASL)可完成对通用寄存器中的内容进行逻辑(或算术)的左移操作,按操作数所指定
    的数量向左移位,低位用零来填充。其中,操作数可以是通用寄存器,也可以是立即数(0~31)。

    操作示例
        MOV R0,R1,LSL #2      ;将R1中的内容左移两位后传送到R0中。

    2.LSR
        LSR的格式为:  通用寄存器,LSR 操作数      

    LSR可完成对通用寄存器中的内容进行右移的操作,按操作数所指定的数量向右移位,左端用
    零来填充。其中,操作数可以是通用寄存器,也可以是立即数(0~31)。

    操作示例: 
        MOV R0,R1,LSR #2   ;将R1中的内容右移两位后传送到R0中,左端用零来填充。

    3.ASR
        ASR的格式为:  通用寄存器,ASR 操作数      

    ASR可完成对通用寄存器中的内容进行右移的操作,按操作数所指定的数量向右移位,左端用
    第31位的符号位来填充。其中,操作数可以是通用寄存器,也可以是立即数(0~31)。

    操作示例:
        MOV R0,R1,ASR #2   ;将R1中的内容右移两位后传送到R0中,左端用第31位的符号位来填充。

    4.ROR
        ROR的格式为:  通用寄存器,ROR 操作数      

    ROR可完成对通用寄存器中的内容进行循环右移的操作,按操作数所指定的数量向右循环移位,
    左端用右端移出的位来填充。其中,操作数可以是通用寄存器,也可以是立即数(0~31)。
    显然,当进行32位的循环右移操作时,通用寄存器中的值不改变。

    操作示例:
        MOV R0,R1,ROR #2      ;将R1中的内容循环右移两位后传送到R0中。

    5.RRX
        RRX的格式为:  通用寄存器,RRX 操作数      

    RRX可完成对通用寄存器中的内容进行带扩展的循环右移的操作,按操作数所指定的数量向右循
    环移位,左端用进位标志位C来填充。其中,操作数可以是通用寄存器,也可以是立即数(0~31)。

    操作示例:
        MOV R0,R1,RRX #2      ;将R1中的内容进行带扩展的循环右移两位后传送到R0中。
 
九、协处理器指令
    协处理器:协助处理器完成一定操作的硬件电路
        协处理器指令:协处理器执行的指令
        ARM 微处理器可支持多达16个协处理器,用于各种协处理操作,在程序执行的过程中,每个
        协处理器只执行针对自身的协处理指令,忽略ARM处理器和其他协处理器的指令。ARM的协处
        理器指令主要用于:
             a、ARM处理器初始化
             b、ARM协处理器的数据处理操作
             c、ARM处理器的寄存器和协处理器的寄存器之间传送数据
             d、ARM协处理器的寄存器和存储器之间传送数据。  

    1、CDP指令
        CDP指令的格式为:
    CDP{条件} 协处理器编码,协处理器操作码1,目的寄存器,源寄存器1,源寄存器2,协处理器操作码2

    CDP指令用于ARM处理器通知ARM协处理器执行特定的操作,若协处理器不能成功完成特定的操作,
    则产生未定义指令异常。其中协处理器操作码1和协处理器操作码2为协处理器将要执行的操作,
    目的寄存器和源寄存器均为协处理器的寄存器,指令不涉及ARM处理器的寄存器和存储器。

    指令示例:
        CDP P3,2,C12,C10,C3,4   ;该指令完成协处理器P3的初始化 

    2.LDC指令
        LDC指令的格式为:  LDC{条件}{L} 协处理器编码,目的寄存器,[源寄存器]
    
    LDC指令用于将源寄存器所指向的存储器中的字数据传送到目的寄存器中,若协处理器不能成功
    完成传送操作,则产生未定义指令异常。其中,{L}选项表示指令为长读取操作,如用于双精度
    数据的传输。
    
    指令示例:
        LDC P3,C4,[R0]      
        ;将ARM处理器的寄存器R0所指向的存储器中的字数据传送到协处理器P3的寄存器C4中。 
    
    3.STC指令
        STC指令的格式为:  STC{条件}{L} 协处理器编码,源寄存器,[目的寄存器]
    
    STC指令用于将源寄存器中的字数据传送到目的寄存器所指向的存储器中,若协处理器不能成功完成传送操作,则产生未定义指令异常。其中,{L}选项表示指 令为长读取操作,如用于双精度数据的传输。
    
    指令示例:
        STC   P3,C4,[R0]     ;将协处理器P3的寄存器C4中的字数据传送到ARM处理 器的寄存器R0所指向的存储器中。 
    
    4、MCR指令
    
    MCR指令的格式为:
    
        MCR{条件} 协处理器编码,协处理器操作码1,源寄存器,目的寄存器1,目的寄存器2,协处理器操作码2。
    
    MCR指令用于将ARM处理器寄存器中的数据传送到协处理器寄存器中,若协处理器不能成功完成操作,则产生未定义指令异常。其中协处理器操作码1和协处理 器操作码2为协处理器将要执行的操作,源寄存器为ARM处理器的寄存器,目的寄存器1和目的寄存器2均为协处理器的寄 存器。
    
    指令示例:
        MCR   P3,3,R0,C4,C5,6     ;将ARM处理器寄存器R0中的数据传送到协处 理器P3的寄存器C4和C5中。 
    
    5、MRC指令
    
    MRC指令的格式为:
    
        MRC{条件} 协处理器编码,协处理器操作码1,目的寄存器,源寄存器1,源寄存器2,协处理器操作码2。
    
    MRC指令用于将协处理器寄存器中的数据传送到ARM处理器寄存器中,若协处理器不能成功完成操作,则产生未定义指令异常。其中协处理器操作码1和协处理 器操作码2为协处理器将要执行的操作,目的寄存器为ARM处理器的寄存器,源寄存器1和源寄存器2均为协处理器的寄存器。
    
    指令示例:
        MRC   P3,3,R0,C4,C5,6     ;该指令将协处理器P3的寄存器中的数据传送到 ARM处理器寄存器中。
    
十、异常产生指令
    1.SWI指令
        SWI指令的格式为:  SWI{条件} 24位的立即数
    
    SWI指令用于产生软件中断,以便用户程序能调用操作系统的系统例程。操作系统在SWI的异常
    处理程序中提供相应的系统服务,指令中24位的立即数指定用户程序调用系统例程的类型,相
    关参数通过通用寄存器传递,当指令中24位的立即数被忽略时,用户程序调用系统例程的类型
    由通用寄存器R0的内容决定,同时,参数通过其他通用寄存器传递。 24位的立即数是中断号
    
    指令示例:
        SWI   0x02           ;该指令调用操作系统编号位02的系统例程。
    
    2.BKPT指令
        BKPT指令的格式为:  BKPT 16位的立即数
    
    BKPT指令产生软件断点中断,可用于程序的调试。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值