ARM常用指令(2)
算术与移位指令
加减法指令
- add指令
立即数加法指令
ARM文档描述如下
ADD Wd|WSP, Wn|WSP, #imm{, shift} ; 32-bit
ADD Xd|SP, Xn|SP, #imm{, shift} ; 64-bit
这里要注意的是立即数的范围是0~4095,但是在实际过程中,写出这种语句编译运行也不会报错: \(add \enspace x0, \enspace x0, \enspace 4096\)
使用汇编与反汇编来看看编译器如何处理的,具体的汇编反汇编命令,可以查看ARM常用指令(1) 中MOV指令讲解。
1
2
3
4
5
6
7
8
9
10
11.arch armv8-a
.text
.align 3
.global test2
test2:
add x0, x0, #4095
add x2, x2, #4096
ret1
2
3
4
5
6
7
8
9
10
11
12
13
14
15main.o: file format elf64-littleaarch64
Contents of section .text:
0000 e10300aa 204040f8 220440f9 00fc3f91 .... @@.".@...?.
0010 42044091 c0035fd6 B.@..._.
Disassembly of section .text:
0000000000000000 <test2>:
0: aa0003e1 orr x1, xzr, x0
4: f8404020 ldur x0, [x1,#4]
8: f9400422 ldr x2, [x1,#8]
c: 913ffc00 add x0, x0, #0xfff
10: 91400442 add x2, x2, #0x1, lsl #12
14: d65f03c0 retadd x0, x0, #4095 实际上为 add x0, x0, #0xfff
add x2, x2, #4096 实际上为 add x2, x2, #0x1, lsl #12
但是如果写成 add x0, x0, #4097编译就会报错 immediate out of range
寄存器加法指令
- 加法指令
1
2add x0, x1, x2, UXTB
// 类似的extend还有UXTB, UXTH, UXTW, UXTX, SXTB, SXTH, SXTW or SXTX.UXT*:零扩展
SXT*:有符号扩展
例如:
1
2
3
4
5
6
7mov x1, #1
mov x2, #0x108a
add x0, x1, x2, UXTB //(1)
add x0, x1, x2, SXTB //(2)
// (1)式结果为0x8B,UXTB取x2寄存器低字节8A做零扩展,与x1寄存器立即数1相加,结果为8B
// (2)式结果为0xFFFFFF8B,SXTB取x2寄存器低字节8A做有符号扩展,与x1寄存器立即数1相加,结果为FFFFFF8B- 移位加法指令
1
add x0, x1, x2, LSL 2
32bit寄存器移位操作数范围为0~31
64bit寄存器移位操作数范围为0~63
减法指令
减法指令与加法指令类似,也分为立即数减法指令,寄存器减法指令。
cmp指令
cmp指令内部调用subs指令实现
1 | cmp x1, x2 |
移位指令
- LSL:逻辑左移,最高位丢弃,最低位补0
- LSR:逻辑右移,最低位丢弃,最高位补0
- ASR:算术右移,最高位符号扩展,最低位丢弃
- ROR:循环右移,最低位移动到最高位
1 | ldr w1, =0x8000008a |
位操作指令
- 与操作
1 | and x0, x1, x2 // x1 = 6, x2 = 1 => x0 = 0 |
- 或操作
1 | orr x0, x1, x2 // x1 = 6, x2 = 1 => x0 = 7 |
- 异或操作
1 | eor x0, x1, x2 // x1 = 4, x2 = 1 => x0 = 5 |
异或操作真值表
0 ^ 0 | 0 |
---|---|
0 ^ 1 | 1 |
1 ^ 0 | 1 |
1 ^ 1 | 0 |
- 0异或任何数为任何数本身
- 1异或任何数为任何数取反
- 任何数异或自己为0
1 | // 1. 实现位翻转 |
- 位清除
1 | // 清除x0中第0、1和3位,保持其余的不变 |
以下为三个目前用的不多的指令
- CLZ指令
1 | // 统计最高位1之前还有几个0 |
- BFI指令
1 | // 用作bit位插入 |
- UBFX
1 | // 位提取指令 |