条件操作码
在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