条件操作码
在 pstate 处理器 (对应 a32 之前是 CPSR) 状态中有 4 个条件操作吗 NCZV
条件标志位 | 描述 |
---|---|
N | 负数标志(上次运算结果为负值,则 N =1, 否则 N =0) |
Z | 上次运算结果为 0 |
C | 对于加法运算,无符号溢出,C=1, 其他不变 |
V | 有符号溢出 |
普通加法指令 add
1. 使用寄存器的加法;
2. 使用立即数的加法;
3. 使用移位操作的加法
adds 指令,影响条件标志位 c
subs 指令,影响条件标志位 c
adc 指令
带进位的加法指令,
ADC Xd, Xn, Xm //Xd = Xn + Xm + c
SBC 指令
SBC Xd, Xn, Xm //Xd = Xn-Xm-1+C
CMP 指令
内部用 subs 指令实现的,影响 C 标志位
cmp x1,x2 //x1+not(x2)+1
当 x1>=x2,C=1
x1<x2, C=0
练习 1:测试 C 条件标志位
.global my_add_test
my_add_test:
mov x0,#0
ldr x1,=0xffffffffffffffff
mov x2,#3
//test adds, influence C flag
adds x0,x1,x1 //update C
adc x3, xzr, xzr
//test for cmp, if x1>x2 ,C=1 ,or C=0
cmp x1, x2
adc x4, xzr, xzr
ret
执行结果如下:
练习 2:cmp 和 sbc 搭配使用
/*
* when arg1 >= arg2, return 0
* when arg1 < arg2, return 0xffffffffffffffff
* SBC Rd,Rn,Rm -->Rd = Rn-RM-1+c
*/
.global my_compare_test
my_compare_test: //param x0,x1, return x0
cmp x0, x1
sbc x0, xzr, xzr //0-0-1+C
ret
移位指令
指令 | 描述 | |
---|---|---|
lsl | 逻辑左移指令 | 低位补零 |
lsr | 逻辑右移指令 | 最高位,永远补零 |
asr | 算数右移 | 左边补位与符号一致 |
ror | 循环右移 | 最右位,移动做最左位 |
按位与操作
AND Xd,Xn -->Xd = Xd & Xn
ANDS 影响 Z 标志位
ands 影响 z 比特位
/*
* ands influence Z flag in pstate
*/
.global my_ands_test
my_ands_test:
mov x1, #0x3
mov x2, #0
ands x3,x1,x2
mrs x0, nzcv //z at 30bit
ret
按位或 / 异或
ORR Xd, Xn -->Xd = Xd | Xn
EOR Xd, Xn -->Xd = Xd ^ Xn
异或的三个特点:
(1)0 异或任何数 = 任何数;
(2)1 异或任何数 = 任何数相反数;
(3)任何数异或自己 =0;
异或的几个技巧运用
(1) 使某些位翻转:
0xffff,ffff ^ 0x1<<5 // 把第 5 位翻转
(2) 交换两个数
a = a^b
b = b^a
a = a^b
(3) 在汇编里设置 0
eor x0,x0
(4) 判断两个数是否相等
return ((a^b)==0)
按位清除
bic: 位清零指令
mov x0 ,0xabcd
bic x0,x0,#0xf
位段操作指令
填充比特位 bfi
提取比特位 bfx
BFI Xd,Xn, #LSB, #WIDTH //get [0,width)from Xn, to [lsb,lsb+width) of Xd
BFX Xd, Xn,#LSB, #WIDTH // get [lab,lsb+width) from Xn, to [x,width)
//ubfx:fill '0' in other bits
//sbuf:fill '1' when bit[lsb+width-1] is 1, or fill '0'
测试程序:
.global my_bitfiled_test
my_bitfiled_test:
mov x0,0xabcd
bic x0,x0,0xf
ldr x6, =0x346
mov x1, 0
bfi x1, x6, #8,#4
ldr x2, =0x5678abcd
ubfx x3, x2, #4, #8
sbfx x4, x2, #4, #8
//read bitfiled from register
mrs x7,ID_AA64ISAR0_EL1
//support LSE?
ubfx x8,x7, #20, #4
//support AES?
ubfx x9, x7, #4, #4
ret
运行结果如下:
零计数指令
clz, 计算最高位 1 前的 0 个数
mov x1, 0xf
clz x2, x1 //x2 为 60
正文完