三.ARM指令
3.1 数据处理指令
3.1.2 MOV指令(数据传送)
MOV R4,R5 ;R4←R5,不更新标志位
MOV R4,#300 ;R4=300,不更新标志位
MOVS R3,R1,LSL #2 ;R3←R1×4,并影响标志位
3.1.3 MVN指令(取反)
MVN R4,R4 ;求反码
3.1.4 ADD指令(加法)
ADD R0,R1,R2 ;R0 ← R1 + R2
ADDS R1,R1,#1 ;R1 ← R1 + 1,并影响标识位
ADDS R3,R1,R2,LSL #2 ;R3 ← R1 + R2 / 2,并影响标志位
Question:如何完成两个64位数的加法?
LDR R0, =0x12345678 ;第一个数的低32位
LDR R1, =0x23456789 ;第一个数的高32位
LDR R2, =0x34567890 ;第二个数的低32位
LDR R3, =0x45678901 ;第二个数的高32位
ADDS R4, R0, R2 ;将两个数的低32位的值相加并且改变CPSR中C位的值
ADC R5, R1, R3 ;带进位的加法
练习:(1)写一条 ARM 指令,完成操作r1 = r2 2
(2)写一条 ARM 指令,完成操作r1 = r2 4
(3)写一条 ARM 指令,完成操作r1 = r2 *3
(1)
MOV R1, R2 LSL #1
(2)
MOV R1, R2 LSL #2
(3)
ADD R1, R2, R2 LSL #1
3.1.5 SUB(减法)
SUB R0,R1,R2 ;R0 ← R1 - R2
SUBS R1,R1,#1 ;R1 ← R1 - 1,并影响标识位
SUBS R3,R1,R2,LSL #2 ;R3 ← R1 - R2 / 2,并影响标志位
Question:如何完成两个64位数的减法?
LDR R0, =0x12345678 ;第一个数的低32位
LDR R1, =0x23456789 ;第一个数的高32位
LDR R2, =0x34567890 ;第二个数的低32位
LDR R3, =0x45678901 ;第二个数的高32位
SUBS R4, R0, R2 ;将两个数的低32位的值相减并且改变CPSR中C位的值
SBC R5, R1, R3 ;带进位的减法
3.1.6 LOOP(循环)
MOV R0, #loopcount ;初始化循环次数
LOOP ;循环体
……
SUBS R0, R0, #1 ;循环计数器减1,设置条件标志
BNE LOOP ;循环计数器不为0,跳到loop继续执行
…… ;循环计数器为0,程序继续执行
编写一段ARM汇编程序段,实现1+2+……+100的运算。
写法一(ADD):
MOV R0, #0
MOV R1, #0
LOOP
ADD R1, R1, R0
CMP R0, #100
ADD R0, R0, #1
BNE LOOP
写法二(SUB):
MOV R0, #100
MOV R1, #0
LOOP
ADD R1, R1, R0
SUBS R0, R0, #1
BNE LOOP
3.1.7 AND/ORR/EOR/BIC(逻辑运算)
ANDS R0, R1, #3 ;R0 = R1 & 3,保持R1的0、1位并更新CPSR
AND R1, R0, #0x01 ;R1 = R0 & 0x01,取出最低位数据
AND R1, R0, #0xF0000000 ;R1 = R0 & 0xF0000000,取出高四位
AND指令可用于提取寄存器中某些位的值。
ORR R0, R0, #3 ;设置R0中0、1位,其余位保持不变
MOV R0, R2, LSR #24 ;R0 ← R2 >> 24(R2高24位为0,将R2低8位传送R0)
ORR R3, R0, R3, LSL #8 ;R3 ← R0 | R3 << 8 (R3低8位为0,结果将R2的)
ORR指令可用于设置寄存器的某些位。
EOR R0, R0, #3 ;反转R0中0、1位,其余位保持不变
EOR指令可用于反转寄存器中某些位的值,将某一位值与0做异或,该位值不变,与1做异或,该位值求反。
BIC R1, R1, #0x0F ;将R1的低4位清0,其它位不变
初始值R1=23H,R2=0FH执行指令BIC R0, R1,R2,LSL #1后,寄存器R0,R1的值分别是多少?
R2 0 0 0 0 1 1 1 1 0FH
R2, LSL, #1 0 0 0 1 1 1 1 0
R1 0 0 1 0 0 0 1 1 23H
BIC R0, R1, R2, LSL #1
R0 0 0 1 0 0 0 0 1 21H
故寄存器R0 = 21H, R1 = 23H
3.1.8 CMP/CMN(比较)
CMP
寄存器Rn的数减去shifter_Operand的数值,并根据操作的结果更新CPSR中相应的标识位。
CMP R0,R1
CMP R0,#100
如何完成两个64位数的比较?
CMP R1, R3 ;比高32位
CMPEQ R0, R2 ;若高32位相同,比低32位
CMN
基于相反数的比较指令,主要作用将寄存器Rn的数加上shifter_Operand的数值,并根据操作的结果更新CPSR中相应的标识位。
CMN R0, R1
CMN R0, #100
3.1.9 TST/TEQ(测试)
TST
TST指令将寄存器Rn的值与shifter_Operand的值按位逻辑“与”操作,根据操作的结果更新CPSR中的相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行。
TST R0, #01 ;判断R0的最低位是否为0
TST Rl, #0x0F ;判断R1的低4位是否为0
TEQ
TEQ指令将寄存器Rn的值与shifter_Operand的值按位逻辑“异或”操作,根据操作的结果更新CPSR中的相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行。
TEQ R0, R1 ;比较R0与R1是否相等(不影响V位和C位)
3.1.10 MUL/MUA(乘法)
MUL(乘法指令)
MUL R1, R2, R3 ;R1 = R2 × R3
MULS R0, R3, R7 ;R0 = R3 × R7
MUA(乘加指令)
MLA R1, R2, R3, R0 ;R1 = R2 × R3 + R0