ARM 汇编指令集

       ARM处理器的指令集可以分为跳转指令、数据处理指令、程序状态寄存器(PSR)处理指令、加载/存储指令、协处理器指令和异常产生指令6大指令

 

一、 跳转指令

        跳转指令用于实现程序流程的跳转,在ARM程序中有以下两种方法可以实现程序流程的跳转

      Ⅰ.使用专门的跳转指令;
      Ⅱ.直接向程序计数器PC写入跳转地址值,通过向程序计数器PC写入跳转地址值,可以实现在4GB的地址空间中的任意跳转,在跳转之前结合使用MOV  LRPC等类似指令,可以保存将来的返回地址值,从而实现在4GB连续的线性地址空间的子程序调用。

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

1B指令

B指令的格式为:

      B{ 条件目标地址

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

B    Label             ;程序无条件跳转到标号Label处执行
CMP R1,#0      ;当CPSR寄存器中的Z条件码置位时,程序跳转到标号Label处执行
BEQ Label       

 

2BL指令

BL指令的格式为:

      BL{ 条件目标地址

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

以下指令:

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

 

3BLX指令

BLX指令的格式为: 

       BLX 目标地址

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

 

4BX指令

BX指令的格式为:

       BX{ 条件目标地址

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

 

二、数据处理指令

         数据处理指令可分为数据传送指令、算术逻辑运算指令 和比较指令等

1)、数据传送指令用于在寄存器存储器之间进行数据的双向传输;

2)、算术逻辑运算指令完成常用的算术与逻辑的运算,该类指令不但将运算结果保存在目的寄存器中,同时更新CPSR中的相应条件标志位

3)、比较指令不保存运算结果,只更新CPSR中相应的条件标志位

数据处理指令共以下16条。

1MOV指令(传送

MOV指令的格式为:

        MOV{ 条件}{S} 目的寄存器,源操作数

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

指令示例:

MOV R1R0                    ;将寄存器R0的值传送到寄存器R1
MOV PCR14                  ;将寄存器R14的值传送到 PC,常用于子程序返回
MOV R1R0LSL3    ;将寄存器R0的值左移3位后传送到R1

 

2MVN指令(求反)

MVN指令的格式为:

        MVN{ 条件}{S} 目的寄存器,源操作数

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

指令示例:

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

 

3CMP指令(比较)

CMP指令的格式为:

        CMP{ 条件操作数1,操作数2

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

指令示例:

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

 

4CMN指令(负数比较)

CMN指令的格式为:

         CMN{ 条件操作数1,操作数2

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

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

 

5TST指令(测试)

TST指令的格式为:

       TST{ 条件操作数1,操作数2

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

指令示例:

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

 

6TEQ指令(测试相等)

TEQ指令的格式为:

        TEQ{ 条件操作数1,操作数2

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

指令示例:

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


7ADD指令(相加)

ADD指令的格式为:

        ADD{ 条件}{S} 目的寄存器,操作数1,操作数2

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

指令示例:

ADD     R0R1R2                  ; R0 = R1 + R2
ADD     R0R1#256                ; R0 = R1 + 256
ADD     R0R2R3LSL#1       ; R0 = R2 + (R3 << 1)

 

8ADC指令(带进位相加)

ADC指令的格式为:

       ADC{ 条件}{S} 目的寄存器,操作数1,操作数2

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

以下指令序列完成两个128位数的加法,第一个数由高到低存放在寄存器R7R4,第二个数由高到低存放在寄存器R11R8,运算结果由高到低存放在寄 存器R3R0

ADDS    R0R4R8          ; 加低端的字
ADCS    R1R5R9          ; 加第二个字,带进位
ADCS    R2R6R10        ; 加第三个字,带进位
ADC      R3R7R11        ; 加第四个字,带进位

 

9SUB指令(相减)

SUB指令的格式为:

       SUB{ 条件}{S} 目的寄存器,操作数1,操作数2

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

指令示例:

SUB     R0R1R2                 ; R0 = R1 - R2
SUB     R0R1#256            ; R0 = R1 - 256
SUB     R0R2R3LSL#1      ; R0 = R2 - (R3 << 1)

 

10~~~~C指令

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

指令示例:

SUBS    R0R1R2        R0 = R1 - R2 - C,并根据结果设置CPSR的进位标志位

 

11R~~~~指令

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

指令示例:
R~~~~     R0R1R2                         ; R0 = R2 – R1
R~~~~     R0R1#256                     ; R0 = 256 – R1
R~~~~     R0R2R3LSL#1           ; R0 = (R3 << 1) - R2

 

12RSC指令(反向带进位减)

RSC指令的格式为:

        RSC{ 条件}{S} 目的寄存器,操作数1,操作数2

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

指令示例:

RSC     R0R1R2           R0 = R2 – R1 - C

 

13AND指令(逻辑位 与)

AND指令的格式为:

       AND{ 条件}{S} 目的寄存器,操作数1,操作数2

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

指令示例:

AND R0R0,#3          ;该指令保持R001位,其余位清零。

 

14ORR指令(逻辑位 或)

ORR指令的格式为:

         ORR{ 条件}{S} 目的寄存器,操作数1,操作数2

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

指令示例:

ORR R0R0,#3        该指令设置R001位,其余位保持不变。

 

15EOR指令(逻辑位 异或)

EOR指令的格式为:

        EOR{ 条件}{S} 目的寄存器,操作数1,操作数2

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

<think>我们正在讨论ARM架构下的汇编指令集。根据引用[2],ARM处理器以其小尺寸、低功耗和性能著称,是32位RISC架构。引用[1]提到ARMv7-A架构中包含了硬件整数除法指令(sdiv和udiv)。引用[3]提到一本关于x86汇编的书籍,但这里我们关注ARM汇编ARM架构的汇编语言是一种低级语言,用于直接控制ARM处理器。以下是一些基本概念和常用指令的介绍: ### 1. **寄存器** ARM架构有16个32位通用寄存器,命名为R0到R15。其中: - R0-R12:通用目的寄存器。 - R13 (SP):堆栈指针(Stack Pointer)。 - R14 (LR):链接寄存器(Link Register),用于存储子程序返回地址。 - R15 (PC):程序计数器(Program Counter)。 此外,还有当前程序状态寄存器(CPSR),用于存储条件标志(如零标志、进位标志等)和当前处理器状态(如模式)。 ### 2. **基本指令格式** ARM指令通常遵循以下格式: ``` <opcode>{<cond>}{S} <Rd>, <Rn>, <Operand2> ``` 其中: - `opcode`:操作码,如MOV、ADD等。 - `cond`:条件执行后缀(可选),如EQ(相等)、NE(不相等)。 - `S`:设置条件标志(可选)。 - `Rd`:目标寄存器。 - `Rn`:第一个操作数寄存器。 - `Operand2`:第二个操作数,可以是寄存器、立即数或移位后的寄存器。 ### 3. **常用指令** #### 数据传送指令 - `MOV`:将数据从一个寄存器或立即数移动到另一个寄存器。 ```assembly MOV R0, #10 @ 将立即数10加载到R0 MOV R1, R0 @ 将R0的值复制到R1 ``` - `LDR`:从内存加载数据到寄存器。 ```assembly LDR R0, [R1] @ 将R1指向的内存地址的内容加载到R0 ``` - `STR`:将寄存器内容存储到内存。 ```assembly STR R0, [R1] @ 将R0的值存储到R1指向的内存地址 ``` #### 算术指令 - `ADD`:加法。 ```assembly ADD R0, R1, R2 @ R0 = R1 + R2 ADD R0, R1, #5 @ R0 = R1 + 5 ``` - `SUB`:减法。 ```assembly SUB R0, R1, R2 @ R0 = R1 - R2 ``` - `MUL`:乘法(32位结果)。 ```assembly MUL R0, R1, R2 @ R0 = R1 * R2 ``` - `SDIV`和`UDIV`:有符号除法和无符号除法(需要硬件支持,如ARMv7-A及以上)。 ```assembly SDIV R0, R1, R2 @ R0 = R1 / R2(有符号) ``` #### 逻辑指令 - `AND`:按位与。 ```assembly AND R0, R1, R2 @ R0 = R1 & R2 ``` - `ORR`:按位或。 ```assembly ORR R0, R1, R2 @ R0 = R1 | R2 ``` - `EOR`:按位异或。 ```assembly EOR R0, R1, R2 @ R0 = R1 ^ R2 ``` - `BIC`:位清除(将Rn中与Operand2中为1的位对应的位清零)。 ```assembly BIC R0, R1, #0xFF @ 清除R1的低8位,结果存R0 ``` #### 分支指令 - `B`:无条件分支(跳转)。 ```assembly B label @ 跳转到标签label处 ``` - `BL`:带链接的分支(用于函数调用),将返回地址存入LR。 ```assembly BL function @ 调用函数function ``` - `BX`:分支并切换指令集(用于Thumb/ARM状态切换)。 ```assembly BX LR @ 返回到LR指定的地址,并可能切换状态 ``` #### 比较指令 - `CMP`:比较两个操作数,设置条件标志。 ```assembly CMP R0, R1 @ 比较R0和R1,设置标志位 ``` - `TST`:测试位(按位与,设置标志但不保存结果)。 ```assembly TST R0, #1 @ 测试R0的最低位 ``` ### 4. **条件执行** ARM指令可以通过添加条件后缀来实现条件执行。例如: ```assembly ADDEQ R0, R1, R2 @ 如果前一条指令导致EQ(相等)条件成立,则执行加法 ``` ### 5. **示例程序** 以下是一个简单的ARM汇编程序,计算1到10的和: ```assembly MOV R0, #0 @ 初始化总和为0 MOV R1, #1 @ 计数器从1开始 loop: ADD R0, R0, R1 @ 累加 ADD R1, R1, #1 @ 计数器加1 CMP R1, #10 @ 比较计数器和10 BLE loop @ 如果小于等于10,则继续循环 @ 此时R0中存储了总和(55) ``` ### 6. **汇编环境** 要编写和运行ARM汇编程序,可以使用交叉编译工具链(如GCC的ARM版本)和模拟器(如QEMU)。例如,使用`arm-linux-gnueabihf-as`和`arm-linux-gnueabihf-gcc`进行汇编和链接。 以上内容是对ARM汇编指令集的简要介绍。ARM汇编语言非常丰富,还包括许多其他指令和特性,如协处理器指令、SIMD指令(NEON)等,可根据需要进一步学习。 §§相关问题§§ 1. ARM架构中条件执行的具体规则是什么? 2. 如何在ARM汇编中实现函数调用和返回? 3. ARMv7和ARMv8架构在指令集上有哪些主要区别? 4. 如何用ARM汇编进行内存访问优化? 5. ARM汇编中的移位操作有哪些?</think>### ARM架构汇编指令集简介与使用 ARM架构是一种精简指令集(RISC)架构,以其低功耗、高性能和小尺寸著称[^2]。其汇编语言用于底层硬件控制和优化。以下是核心概念和用法: --- ### 一、ARM汇编基础 #### 1. **寄存器** - **16个32位通用寄存器**:R0-R12(数据操作),R13(SP:堆栈指针),R14(LR:链接寄存器),R15(PC:程序计数器)[^2]。 - **特殊寄存器**:CPSR(当前程序状态寄存器),存储条件标志(如零标志Z、进位标志C)。 #### 2. **指令格式** ARM指令通常为 **`操作码 目标寄存器, 操作数1, 操作数2`** 格式: ```assembly ADD R0, R1, R2 @ R0 = R1 + R2 SUB R3, R4, #10 @ R3 = R4 - 立即数10 ``` #### 3. **寻址模式** - **立即数寻址**:`MOV R0, #0xFF` - **寄存器寻址**:`ADD R1, R2, R3` - **寄存器间接寻址**:`LDR R0, [R1]`(从R1指向的内存加载数据) - **基址偏移寻址**:`STR R2, [R3, #4]`(地址为R3+4) --- ### 二、核心指令分类 #### 1. **数据传送** - `MOV R0, R1` @ 寄存器间复制 - `LDR R0, [R1]` @ 从内存加载到寄存器 - `STR R0, [R1]` @ 将寄存器值存储到内存 - `PUSH {R0, R1}` @ 压栈,`POP {R0, R1}` @ 弹栈 #### 2. **算术运算** - `ADD/SUB R0, R1, R2` @ 加/减 - `MUL R0, R1, R2` @ 乘法 - `SDIV/UDIV R0, R1, R2` @ 有符号/无符号除法(需硬件支持)[^1] #### 3. **逻辑运算** - `AND/ORR/EOR R0, R1, R2` @ 与/或/异或 - `LSL R0, R1, #2` @ 逻辑左移2位 - `ASR R0, R1, #3` @ 算术右移3位 #### 4. **控制流** - `B label` @ 无条件跳转 - `BL label` @ 跳转并保存返回地址到LR(用于函数调用) - `BX LR` @ 函数返回 - `CMP R0, R1` @ 比较R0和R1(设置CPSR标志) - `BEQ label` @ 若相等则跳转(基于CPSR) #### 5. **条件执行** 几乎所有指令可加条件后缀(如`ADDEQ`),提升效率: ```assembly CMP R0, #0 @ 检查R0是否为0 MOVEQ R1, #1 @ 若为0,则R1=1 MOVNE R1, #0 @ 若不为0,则R1=0 ``` --- ### 三、使用示例 #### 1. **函数调用与返回** ```assembly main: BL my_function @ 调用函数,返回地址存入LR ... my_function: PUSH {R4, LR} @ 保存寄存器 ... @ 函数逻辑 POP {R4, LR} @ 恢复寄存器 BX LR @ 返回 ``` #### 2. **内存访问优化** ```assembly LDR R0, [R1], #4 @ 加载R1指向的值后,R1自增4(自动后变址) STR R2, [R3, #8]! @ 存储前将R3+8(前变址) ``` #### 3. **循环求和(1到10)** ```assembly MOV R0, #0 @ 总和初始化为0 MOV R1, #1 @ 计数器i=1 loop: ADD R0, R0, R1 @ 累加 ADD R1, R1, #1 @ i++ CMP R1, #10 @ 检查i<=10 BLE loop @ 满足则继续循环 ``` --- ### 四、开发工具与注意事项 1. **工具链**: - 汇编器:`arm-linux-gnueabi-as` - 调试器:GDB + QEMU模拟器 - 编译器:GCC(`-S`选项生成汇编代码) 2. **关键特性**: - **Thumb模式**:16位指令集,代码密度更高。 - **条件执行**:减少分支指令,提升性能[^3]。 - **小端序**:数据存储与x86一致[^2]。 3. **内存操作**: - 需对齐访问(如LDR/STR地址需4字节对齐)。 - 使用`LDM/STM`批量加载/存储提高效率: ```assembly LDMIA R1!, {R2-R5} @ 从R1连续加载4个寄存器,R1自增 ``` --- ### 五、ARMv8扩展(64位) - 寄存器扩展至64位(X0-X30)。 - 新增指令如`LDP`(加载双寄存器): ```assembly LDP X0, X1, [X2] @ 从X2加载两个64位值到X0和X1 ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值