ARM——汇编指令集

本文深入解析ARM指令集,包括算数运算、逻辑运算等核心指令的详细解释与应用实例,如加法、减法、逻辑与、逻辑或、位清除等,适用于嵌入式系统开发者深入了解ARM处理器工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

指令总结

算数运算

 逻辑运算

1. ADC : 带进位的加法

2. ADD : 加法

3. AND : 逻辑与

4. BIC : 位清除

5. EOR : 逻辑异或

6. MOV : 传送

7. MVN : 传送取反的值

8. ORR : 逻辑或

9. RSB : 反向减法

10. RSC : 带借位的反向减法

11. SBC : 带借位的减法

12. SUB : 减法

13. MOV 指令

14. MRS 指令

15. MSR 指令

16. LDR 指令

17. STR 指令

18. B 指令


指令总结

算数运算

指令计算公式备注
ADD Rd, Rn, RmRd = Rn + Rm加法运算,指令为 ADD
ADD Rd, Rn, #immedRd = Rn + #immed
ADC Rd, Rn, RmRd = Rn + Rm + 进位带进位的加法运算,指令为 ADC
ADC Rd, Rn, #immedRd = Rn + #immed +进位
SUB Rd, Rn, RmRd = Rn – Rm减法
SUB Rd, #immedRd = Rd - #immed
SUB Rd, Rn, #immedRd = Rn - #immed
SBC Rd, Rn, #immedRd = Rn - #immed – 借位带借位的减法
SBC Rd, Rn ,RmRd = Rn – Rm – 借位
MUL Rd, Rn, RmRd = Rn * Rm乘法(32 位)
UDIV Rd, Rn, RmRd = Rn / Rm无符号除法
SDIV Rd, Rn, RmRd = Rn / Rm有符号除法

 逻辑运算

指令计算公式备注
AND Rd, RnRd = Rd &Rn按位与
AND Rd, Rn, #immedRd = Rn &#immed
AND Rd, Rn, RmRd = Rn & Rm
ORR Rd, RnRd = Rd | Rn按位或
ORR Rd, Rn, #immedRd = Rn | #immed
ORR Rd, Rn, RmRd = Rn | Rm
BIC Rd, RnRd = Rd & (~Rn)位清除
BIC Rd, Rn, #immedRd = Rn & (~#immed)
BIC Rd, Rn , RmRd = Rn & (~Rm)
ORN Rd, Rn, #immedRd = Rn | (#immed)按位或非
ORN Rd, Rn, RmRd = Rn | (Rm)
EOR Rd, RnRd = Rd ^ Rn按位异或
EOR Rd, Rn, #immedRd = Rn ^ #immed
EOR Rd, Rn, RmRd = Rn ^ Rm

1. ADC : 带进位的加法

(Addition with Carry)

ADC{条件}{S}  <dest>, <op 1>, <op 2>

                dest = op_1 + op_2 + carry

ADC将把两个操作数加起来,并把结果放置到目的寄存器中。它使用一个进位标志位,这样就可以做比 32 位大的加法。下列例子将加两个 128 位的数。

128 位结果: 寄存器 0、1、2、和 3
第一个 128 位数: 寄存器 4、5、6、和 7
第二个 128 位数: 寄存器 8、9、10、和 11。

  ADDS    R0, R4, R8              ; 加低端的字

  ADCS    R1, R5, R9              ; 加下一个字,带进位

  ADCS    R2, R6, R10             ; 加第三个字,带进位

  ADCS    R3, R7, R11             ; 加高端的字,带进位

如果如果要做这样的加法,不要忘记设置 S 后缀来更改进位标志。

2. ADD : 加法

(Addition)

ADD{条件}{S}  <dest>, <op 1>, <op 2>

                dest = op_1 + op_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)

加法可以在有符号和无符号数上进行。

3. AND : 逻辑与

(logical AND)

AND{条件}{S}  <dest>, <op 1>, <op 2>

                dest = op_1 AND op_2

AND将在两个操作数上进行逻辑与,把结果放置到目的寄存器中;对屏蔽你要在上面工作的位很有用。操作数 1 是一个寄存器,操作数2 可以是一个寄存器,被移位的寄存器,或一个立即值:

AND     R0, R0, #3              ; R0 = 保持 R0 的位 0 和 1,丢弃其余的位。

4. BIC : 位清除

(Bit Clear)

BIC{条件}{S}  <dest>, <op 1>, <op 2>

                dest = op_1 AND (!op_2)

BIC是在一个字中清除位的一种方法,与 OR 位设置是相反的操作。操作数 2 是一个 32 位位掩码(mask)。如果如果在掩码中设置了某一位,则清除这一位。未设置的掩码位指示此位保持不变。

BIC     R0, R0, #%1011          ; 清除 R0 中的位 0、1、和 3。保持其余的不变。 

5. EOR : 逻辑异或

(logical Exclusive OR)

EOR{条件}{S}  <dest>, <op 1>, <op 2>

                dest = op_1 EOR op_2

EOR将在两个操作数上进行逻辑异或,把结果放置到目的寄存器中;对反转特定的位有用。操作数 1 是一个寄存器,操作数 2 可以是一个寄存器,被移位的寄存器,或一个立即值:

EOR     R0, R0, #3              ; 反转 R0 中的位 0 和 1

EOR 真值表(二者不同则结果为 1)。

6. MOV : 传送

(Move)

MOV{条件}{S}  <dest>, <op 1>

                dest = op_1

MOV从另一个寄存器、被移位的寄存器、或一个立即值装载一个值到目的寄存器。你可以指定相同的寄存器来实现 NOP 指令的效果,你还可以专门移位一个寄存器:

  MOV     R0, R0                  ; R0 = R0... NOP 指令

  MOV     R0, R0, LSL#3      ; R0 = R0 * 8

如果 R15 是目的寄存器,将修改程序计数器或标志。这用于返回到调用代码,方法是把连接寄存器的内容传送到 R15:

  MOV     PC, R14                 ; 退出到调用者

  MOVS    PC, R14                ; 退出到调用者并恢复标志位

7. MVN : 传送取反的值

(MoveNegative)

MVN{条件}{S}  <dest>, <op 1>

                dest = !op_1

MVN从另一个寄存器、被移位的寄存器、或一个立即值装载一个值到目的寄存器。不同之处是在传送之前位被反转了,所以把一个被取反的值传送到一个寄存器中。这是逻辑非操作而不是算术操作,这个取反的值加 1 才是它的取负的值:

  MVN     R0, #4                  ; R0 = -5

  MVN     R0, #0                  ; R0 = -1

8. ORR : 逻辑或

(logical OR)

ORR{条件}{S}  <dest>, <op 1>, <op 2>

                dest = op_1 OR op_2

OR将在两个操作数上进行逻辑或,把结果放置到目的寄存器中;对设置特定的位有用。操作数 1 是一个寄存器,操作数 2 可以是一个寄存器,被移位的寄存器,或一个立即值:

ORR     R0, R0, #3              ; 设置 R0 中位 0 和 1

OR 真值表(二者中存在 1 则结果为 1)。

9. RSB : 反向减法

(Reverse Subtraction)

RSB{条件}{S}  <dest>, <op 1>, <op 2>

                dest = op_2 - op_1

SUB用操作数two 减去操作数one,把结果放置到目的寄存器中。操作数 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

反向减法可以在有符号或无符号数上进行。

10. RSC : 带借位的反向减法

(Reverse Subtraction with Carry)

RSC{条件}{S}  <dest>, <op 1>, <op 2>

                dest = op_2 - op_1 - !carry

同于SBC,但倒换了两个操作数的前后位置。

11. SBC : 带借位的减法

(Subtraction with Carry)

SBC{条件}{S}  <dest>, <op 1>, <op 2>

                dest = op_1 - op_2 - !carry

SBC做两个操作数的减法,把结果放置到目的寄存器中。它使用进位标志来表示借位,这样就可以做大于 32 位的减法。SUB和SBC生成进位标志的方式不同于常规,如果需要借位则清除进位标志。所以,指令要对进位标志进行一个操作 - 在指令执行期间自动的反转此位。

12. SUB : 减法

(Subtraction)

SUB{条件}{S}  <dest>, <op 1>, <op 2>

                dest = op_1 - op_2

SUB用操作数one 减去操作数 two,把结果放置到目的寄存器中。操作数 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)

减法可以在有符号和无符号数上进行。

13. MOV 指令

MOV 指令用于将数据从一个寄存器拷贝到另外一个寄存器,或者将一个立即数传递到寄存器里面,使用示例如下:

MOV R0, R1  @将寄存器 R1 中的数据传递给 R0,即 R0=R1
MOV R0, #0X12  @将立即数 0X12 传递给 R0 寄存器,即 R0=0X12

14. MRS 指令

MRS 指令用于将特殊寄存器(如 CPSR 和 SPSR)中的数据传递给通用寄存器,要读取特殊寄存器的数据只能使用 MRS 指令!使用示例如下:

MRS R0, CPSR@将特殊寄存器 CPSR 里面的数据传递给 R0,即 R0=CPSR

15. MSR 指令

MSR 指令和 MRS 刚好相反, MSR 指令用来将普通寄存器的数据传递给特殊寄存器,也就是写特殊寄存器,写特殊寄存器只能使用 MSR,使用示例如下:

MSR CPSR, R0 @将 R0 中的数据复制到 CPSR 中,即 CPSR=R0

16. LDR 指令

LDR 主要用于从存储加载数据到寄存器 Rx 中, LDR 也可以将一个立即数加载到寄存器 Rx中, LDR 加载立即数的时候要使用“=”,而不是“#”。在嵌入式开发中, LDR 最常用的就是读取 CPU 的寄存器值,比如有个寄存器 GPIO1_GDIR,其地址为 0X0209C004,我们现在要读取这个寄存器中的数据,示例代码如下:

LDR R0, =0X0209C004 @将寄存器地址 0X0209C004 加载到 R0 中,即 R0=0X0209C004

LDR R1, [R0] @读取地址 0X0209C004 中的数据到 R1 寄存器中

上述代码就是读取0X0209C004 地址对应的寄存器中的值,读取到的寄存器值保存在 R1 寄存器中,上面代码中 offset 是 0,也就是没有用到 offset。

17. STR 指令

LDR 是从存储器读取数据, STR 就是将数据写入到存储器中,同样以地址0X0209C004的寄存器为例,现在我们要配置寄存器 的值为 0X2000002,示例代码如下:

LDR R0, =0X0209C004 @将寄存器地址 0X0209C004 加载到 R0 中,即 R0=0X0209C004

 LDR R1, =0X20000002 @R1 保存要写入到寄存器的值,即 R1=0X20000002

STR R1, [R0] @将 R1 中的值写入到 R0 中所保存的地址中

LDR 和 STR 都是按照字进行读取和写入的,也就是操作的 32 位数据,如果要按照字节、半字进行操作的话可以在指令“LDR”后面加上 B 或 H,比如按字节操作的指令就是 LDRB 和STRB,按半字操作的指令就是 LDRH 和 STRH。

18. B 指令

这是最简单的跳转指令, B 指令会将 PC 寄存器的值设置为跳转目标地址, 一旦执行 B 指令, ARM 处理器就会立即跳转到指定的目标地址。如果要调用的函数不会再返回到原来的执行处,那就可以用 B 指令,如下示例:

_start:


 ldr sp,=0X80200000 @设置栈指针
 b main @跳转到 main 函数

上述代码只是初始化了 SP 指针,有些处理器还需要做其他的初始化,比如初始化 DDR 等等。

因为跳转到 C 文件以后再也不会回到汇编了,所以使用了 B 指令来完成跳转。

19. STR指令

STR{条件}  源寄存器,<存储器地址>

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

指令示例:

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

STR R0,[R1,#8]             ;将R0中的字数据写入以R1+8为地址的存储器中。

str     r1, [r0]                       ;将r1寄存器的值,传送到地址值为r0的(存储器)内存中

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值