指令系统3(算数运算指令)
一.加法指令(ADD):
用于执行 16 位或 32 位的加法运算。
- 指令格式及功能:
ADD Rd, Rm
:将寄存器Rd
和Rm
的值相加,结果存回Rd
,即Rd = Rd + Rm
。ADD Rd, Rn, Rm
:把寄存器Rn
和Rm
的值相加,结果存入Rd
,Rd = Rn + Rm
。ADD Rd, #imm
:imm
为 8 位或 16 位立即数,将Rd
的值与立即数相加,Rd = Rd + imm
。例如ADD R0, #0x12
,执行后R0 = R0 + 0x12
。ADD.W Rd, Rn, Rm
:显式指定为 32 位指令,Rd = Rn + Rm
。
- 标志位影响:16 位加法会自动更新 APSR(应用程序状态寄存器)中的标志位;使用
W
指定 32 位指令时,通过S
后缀控制对 APSR 的更新,如ADD.W R0, R1, R2
不更新标志位,ADDS.W R0, R1, R2
更新标志位。
二.带进位加法指令(ADC):
进行 16 位或 32 位带进位的加法运算。
- 指令格式及功能:
ADC Rd, Rn
:将Rd
、Rn
的值与进位标志C
相加,结果存回Rd
,即Rd = Rd + Rn + C
。ADC Rd, #imm
:imm
为 12 位立即数,Rd = Rd + imm + C
。ADC Rd, Rn, Rm
:Rd = Rn + Rm + C
。例如ADC.W R0, R1, R2
,执行R0 = R1 + R2 + C
。
- 标志位影响:与 ADD 指令类似,
ADC.W R0, R1, R2
不更新标志位,ADCS.W R0, R1, R2
更新标志位。
三.64 位加法举例:
- 计算两个 64 位数的和,假设
R0
、R1
为被加数,R2
、R3
为加数。- 方法一(16位):
MOV R0, #1 LDR R1, =0X80000001 MOV R2, #2 LDR R3, =0XFFFF0001 ADD R1, R3 ADC R0, R2
- 方法二(32位):
MOV R0, #1 LDR R1, =0X80000001 MOV R2, #2 LDR R3, =0XFFFF0001 ADDS.W R1, R1, R3 ADC.W R0, R0, R2
- 运行结果:
R1 = 0X7FFF0002
,R0 = 0X00000003
。
- 方法一(16位):
四.减法指令(SUB):
- 实现 16 位或 32 位的减法运算。
- 指令格式及功能:
SUB Rd, Rn
:从Rd
中减去Rn
的值,结果存回Rd
,即Rd = Rd - Rn
。SUB Rd, #imm
:imm
为 8 位或 16 位,Rd = Rd - imm
。例如SUB R0, #0xf1
,执行后R0 = R0 - 0xf1
。SUB Rd, Rn, Rm
:用Rn
减去Rm
的值,结果存入Rd
,Rd = Rn - Rm
。SUB.W Rd, Rn, Rm
:32 位减法指令,Rd = Rn - Rm
。
- 标志位影响:与 ADD 指令类似,
SUB.W R0, R1, R2
不更新标志位,SUBS.W R0, R1, R2
更新标志位。
- 指令格式及功能:
五.带借位减法指令(SBC):
- 执行 16 位或 32 位带借位的减法运算。
- 指令格式及功能:
SBC Rd, Rn
:Rd = Rd - Rn - (~C)
,其中~C
表示进位标志C
的取反。SBC Rd, #imm
:imm
为 8 位或 16 位,Rd = Rd - imm - (~C)
。SBC Rd, Rn, Rm
:Rd = Rn - Rm - (~C)
。例如SBC.W R0, R1, R2
,R0 = R1 - R2 - (~C)
。
- 标志位影响:与 ADD 指令类似,
SBC.W R0, R1, R2
不更新标志位,SBCS.W R0, R1, R2
更新标志位。
- 指令格式及功能:
六.逆向减法指令(RSB):
- 指令格式及功能:
RSB.W Rd, Rn, #imm12
:用 12 位立即数imm12
减去Rn
的值,结果存入Rd
,即Rd = imm12 - Rn
。例如RSB.W R8, R6, #240
,执行后R8 = 240 - R6
。RSB.W Rd, Rn, Rm
:用Rm
减去Rn
的值,结果存入Rd
,Rd = Rm - Rn
。
七.64 位减法举例:
- 计算两个 64 位数的差,假设
R0
、R1
为被减数,R2
、R3
为减数。- 方法一(16位):
MOV R0, #0 MOV R1, #1 MOV R2, #0 MOV R3, #2 SUB R1, R3 SBC R0, R2
- 方法二(32位):
MOV R0, #0 MOV R1, #1 MOV R2, #0 MOV R3, #2 SUBS.W R1, R1, R3 SBC.W R0, R0, R2
- 运行结果:
R1 = 0XFFFFFFFE
,R0 = 0XFFFFFFFE
。
- 方法一(16位):
八.比较指令(CMP):
- 比较两个操作数的值,影响 APSR 标志位。
- 指令格式及功能:
CMP Rd, Rn
:将Rd
与Rn
相减,但不存储结果,仅影响 APSR 标志位。CMP Rd, #imm
:imm
为 8 位或 16 位,将Rd
与立即数相减,影响 APSR 标志位。例如CMP R0, R1
,用于比较R0
和R1
的值,影响 APSR 标志位。
- 指令格式及功能:
九.乘法指令(MUL):
- 执行乘法运算。
- 指令格式及功能:
MOV R1, #3 MOV R3, #2 MUL.W R1, R1, R3
执行后
R1 = 6
。MUL Rd, Rm
:将Rd
与Rm
相乘,结果存回Rd
,即Rd = Rd * Rm
。MUL.W Rd, Rn, Rm
:将Rn
与Rm
相乘,结果存入Rd
,Rd = Rn * Rm
。 例如:
- 指令格式及功能:
十.带符号的 64 位乘法:
- 指令格式:
SMULL RL, RH, Rm, Rn
,(RH, RL) = Rm * Rn
,将Rm
和Rn
带符号相乘,结果的低 32 位存于RL
,高 32 位存于RH
。 - 示例:
MOV R0, #1 MOV R1, #-2 SMULL R2, R3, R0, R1
运行结果:R2 = 0XFFFFFFFE
,R3 = 0XFFFFFFFE
。
十一.无符号的 64 位乘法:
- 指令格式:
UMULL RL, RH, Rm, Rn
,(RH, RL) = Rm * Rn
,将Rm
和Rn
无符号相乘,结果的低 32 位存于RL
,高 32 位存于RH
。 - 示例:
MOV R0, #1 MOV R1, #-2 UMULL R2, R3, R0, R1
运行结果:R2 = 0XFFFFFFFE
,R3 = 0X00000000
。
十二.乘加指令(MLA)与乘减指令(MLS):
- 指令格式及功能:
MLA Rd, Rm, Rn, Ra
:先计算Rm
和Rn
的乘积,再加上Ra
,结果存入Rd
,即Rd = Ra + Rm * Rn
。MLS Rd, Rm, Rn, Ra
:先计算Rm
和Rn
的乘积,再用Ra
减去该乘积,结果存入Rd
,Rd = Ra - Rm * Rn
。
- 示例:计算
x * y + z
。MOV R0, #x MOV R1, #y MOV R2, #z MLA R3, R0, R1, R2
十三.除法指令:
- 指令格式及功能:
SDIV Rd, Rn, Rm
:执行带符号除法,Rd = Rn / Rm
。UDIV Rd, Rn, Rm
:执行无符号除法,Rd = Rn / Rm
,余数被丢弃。
- 异常处理:为捕捉被零除的非法操作,可在 NVIC(嵌套向量中断控制器)的配置控制寄存器中置位
DIVBZERO
位。若出现被零除情况,会引发用法 fault 异常;若无处理措施,除数为零时Rd
将被清零。 - 示例:
MOV R0, #3 MOV R1, #2 UDIV R2, R0, R1
运行结果:R2 = 0X00000001
。