- 数据搬移指令:
- 立即数:
- 在待判断的32位数(
以十六进制展开
)中,寻找一个0~255
(即0x00~0xff
)之间的数值,然后将这个数值循环右移
偶数个位置,可以得到待判断的数,即为立即数
;
mov //将第二个操作数直接赋值给目标寄存器
mvn //将第二个操作数按位取反,然后再赋值给目标寄存器
- 示例代码:
.text
.global _start
_start:
mov r0, #0x0000ff00 @第二个操作数为立即数,立即数前需要添加“#”
mov r1, r0 @实现功能:r1 = r0 = 0x0000ff00
mvn r2, #0x0000ff00 @r2 = ~0x0000ff00 = 0xffff00ff
mvn r3, r2 @ r3 = ~r2 = 0x0000ff00
stop:
b stop
.end
- 运行结果:
- ldr伪指令:
- 示例代码:
.text
.global _start
_start:
ldr r0, =0x52985298 @数值可以是0~4G(0~2^32)之间的任意数
stop:
b stop
.end
- 运行结果:
- 移位操作指令:
lsl //逻辑左移或者无符号左移
lsr //逻辑右移或者无符号右移
asr //算数右移或者有符号右移
ror //循环右移
- 示例代码:
.text
.global _start
_start:
/*
lsl //逻辑左移或者无符号左移
lsr //逻辑右移或者无符号右移
asr //算数右移或者有符号右移
ror //循环右移
*/
@逻辑左移:高位移位,低位补0
ldr r0, =0x000000ff
lsl r1,r0, #4 @ r1 = r0 << 4 = 0x00000ff0
@逻辑右移:低位移出,高位补0
lsr r2,r0, #4 @ r2 = r0 >> 4 = 0x0000000f
@算数右移:低位移出,高位补符号位
mov r3,#-0xff @ r3 = 0xffffff01
asr r4,r3, #4 @ r4 = 0xfffffff0
@循环右移:低位移出,补到高位
ror r5,r0, #8 @ r5 = 0xff000000
stop:
b stop
.end
-
运行结果:
-
位运算指令:
-
记忆技巧:
-
与0清0,与1不变;
-
或1置1,或0不变;
-
异或1取反,异或0不变;
and //按位与(&)
orr //按位或(|)
eor //按位异或(^)
bic //按位清除的指令
- 示例代码:
.text
.global _start
_start:
ldr r0, = 0x12345678
@将r0寄存器的第7位置1
orr r0,r0,#(0x1 << 7)
@orr r0,r0, #(1 << 7)
@orr r0,r0, #0x80
@将r0寄存器的第27位清零,并保证其他位不变,新的操作数移到r1
and r0,r0,#(~(0x1 << 27))
mov r1,r0
@将r0寄存器的第20位到第25位置1,并保证其他位不变,新的操作数移到r2
orr r0,r0,#(0x3f << 20)
mov r2,r0
@将r0寄存器的第12位到第18位清0,并保证其他位不变,新的操作数移到r3
and r0,r0, #(~(0x7f << 12))
mov r3,r0
@将r0寄存器的第11位到第4位修改为0b01101101,并保证其他位不变,新的操作数移到r4
and r0,r0, #(~(0xff << 4))
orr r0,r0, #(0x6d << 4)
mov r4,r0
@若第一个寄存器和目标寄存器的编号相同时,可以合并,只写一个寄存器即可
orr r0, #(0x1 << 7) @ r0 |= (0x1 << 7)
mov r5,r0
@将r0寄存器的第7位清0
bic r0, #(0x1 << 7)
mov r6,r0
stop:
b stop
.end
-
运行结果:
-
算数运算指令:
add //普通加法指令,不需要考虑进位标志位(C位)
adc //带进位的加法指令,需要考虑进位标志位(C位)
sub //普通减法指令,不需要考虑借位标志位(C位)
sbc //带借位的减法指令,需要考虑借位标志位(C位)
mul //乘法指令
div //除法指令(ARM-v8之后的架构支持除法指令)
- 示例代码:
.text
.global _start
_start:
/* 案例1:实现两个64位数据的加法运算
第1个64位数据,低32位保存到R0中,高32位保存到R1中;
第2个64位数据,低32位保存到R2中,高32位保存到R3中;
运算结果:低32位保存到R4中,高32位保存到R5中; */
@ 1. 准备2个64位数据
mov r0, #0xFFFFFFFE @ 第1个64位数据的低32位
mov r1, #0x5 @ 第1个64位数据的高32位
mov r2, #0x6 @ 第2个64位数据的低32位
mov r3, #0x7 @ 第2个64位数据的高32位
@ 低32位的加法运算
adds r4, r0, r2 @ r4 = r0 + r2 = 0x0000_0004
@ 高32位的加法运算 @ r5 = r1 + r3 + C = 0x0000_000D
adc r5, r1, r3
/* 案例1:实现两个64位数据的减法运算
第1个64位数据,低32位保存到R0中,高32位保存到R1中;
第2个64位数据,低32位保存到R2中,高32位保存到R3中;
运算结果:低32位保存到R4中,高32位保存到R5中; */
@ 1. 准备2个64位数据
mov r0, #0x4 @ 第1个64位数据的低32位
mov r1, #0xF @ 第1个64位数据的高32位
mov r2, #0x6 @ 第2个64位数据的低32位
mov r3, #0x7 @ 第2个64位数据的高32位
@ 低32位减法运算
subs r4, r0, r2 @ r4 = r0 - r2 = 0xFFFF_FFFE
sbc r5, r1, r3 @ r5 = r1 - r3 - !C = 0x0000_0007
@ 案例3:乘法指令
mov r0, #3
mov r1, #4
mul r2, r0, r1 @ r2 = r0 * r1 = 0xC
@ 乘法指令的第二个操作数只能是一个寄存器
@ mul r3, r0, #5 @ Error
stop:
b stop
.end
-
运行结果:
-
比较指令:
-
功能:比较两个数的大小 ;
-
本质:比较指令的本质做减法运算;
-
比较指令没有目标寄存器,指令的执行结果影响的是CPSR的NZCV位,并且不需要加S;
-
比较指令经常和条件码配合使用,实现汇编指令的有条件执行;
cmp //比较两个数的大小
- 示例代码:
.text
.global _start
_start:
mov r0, #16
mov r1, #19
mov r2, #16
mov r3, #19
cmp r1,r0
subhi r1,r1,r0 @无符号大于
cmp r2,r3
subcc r3,r3,r2 @无符号小于
stop:
b stop
.end
- 运行结果: