这篇博客主要讲下ARM汇编中的数据处理指令,这类指令包括数据传送指令、算数运算指令、逻辑运算指令、比较指令等,下面详细归类说明下。
格式:MOV{条件}{S}目标寄存器, 源操作数
用法:MOV指令可以完成从 另一个寄存器 、 被移位的寄存器 或者 将一个立即数 加载到 目标寄存器 中。其中S选项决定指令的操作是否影响CPSR中条件标志位的值,当没有S时指令不更新CPSR中条件标志位的值。
示例:
MOV R1, R0 ; 将寄存器R0的值传送到寄存器R1中去(从另一个寄存器中)
MOV PC, R14 ; 将寄存器R14的值传送到PC中去,常用于子程序的返回(从另一个寄存器中)
MOV PC, LR ; 效果和上面一句一样,常用于子程序的返回
MOV R1, R0, LSL#3 ; 将寄存器R0的值左移3位后传到R1(从被移位的寄存器中)
MOV R1, #0xF000000B ; 将立即数#0xF000000B放到R1中(将立即数加载到寄存器中)
MOVS R3, R1, LSL#2 ; R3=R1<<2,同时影响标志位
格式:MVN{条件}{S}目标寄存器, 源操作数
用法:用法和MOV一样,完成从 另一个寄存器 、 被移位的寄存器 或者 将一个立即数 加载到 目标寄存器 中,只不过加载的这个数需要先按位取反。
示例:
MVN R0, 0xA0000007 ; 执行的结果相当于R0=0x5FFFFFF8,可以使用朱老师的寄存器验证
MVN R0, #4
; 先对4进行2进制表示,得到0b00000100,取反得到0b11111011,求其补码,因为是负数,先
对其正数01111011求反得到0b10000100,然后加1得到0b10000101 = -5
; 负数的补码求法:正数取反 + 1
格式: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),加上一个移位寄存器内的数据后赋值
格式:SUB{条件}{S} 目标寄存器, 操作数1, 操作数2
用法:SUB指令用于把两个操作数相减,并将结果存放到目标寄存器中。操作数1应该是一个寄存器,操作数2可以是 一个寄存器 、 被移位的寄存器 或者是一个 立即数。
示例:
SUB R0, R1, #256 ; R0 = R1 - 256
格式:RSB{条件}{S} 目标寄存器, 操作数1, 操作数2
用法:作反向减法用的,可从操作数2中减去操作数1,并赋值给目标寄存器。这个是很有用的,因为有了这个指令,操作数2选项范围会更大。
示例:
RSB R1, R0, #5 ; 相当于R1 = 5 - R0
RSB R0, R1, R2 ; 相当于R0 = R2 - R1
RSB R0, R2, R3, LSL#1 ; 相当于R0 = (R3 << 1) - R2
格式:ADC{条件}{S} 目标寄存器, 操作数1, 操作数2
用法:带进位加法,该指令可以将操作数1和操作数2相加,同时带有进位标志。
示例:
; 编写两个64位数相加,第一个64位的低32位放在R0,高32位放在R1
; 第二个64位的数低32位放在R2,高32位放在R3
; 编写代码实现两个64位数的和,结果的低32位放在R4,高32位放在R5
MOV R0, #0xFFFFFFFE ; 第一个数的低32位
MOV R1, #1 ; 第一个数的高32位
MOV R2, #0x5 ; 第二个数的低32位
MOV R3, #1 ; 第二个数的高32位
ADDS R4, R0, R2
ADC R5, R1, R3 ; ADC运算的实质是R5 = R1 + R3 + 'C','C'位是CPSR进位标志
格式:SBC{条件}{S} 目标寄存器, 操作数1, 操作数2
用法:带进位减法,该指令可以从操作数1减去操作数2。如果清除进位标志位,则结果减1。
示例:
MOV R0, #1 ; 第一个数的低32位
MOV R1, #3 ; 第一个数的高32位
MOV R2, #3 ; 第二个数的低32位
MOV R3, #1 ; 第二个数的高32位
SUBS R4, R0, R2
SBC R5, R1, R3
格式:RSC{条件}{S} 目标寄存器, 操作数1, 操作数2
用法:带进位反向减法,指令可以让操作数2减去操作数1中的值,如果清除进位标记,则结果将减1。