前言
本次是该系列的的第0x14篇,一个新的求平均值写法
实验环境:
- Windows10 + VS2022 + masm
0x14
代码片段链接:xorpd | xchg rax,rax 0x14
mov rcx,rax
and rcx,rdx
xor rax,rdx
shr rax,1
add rax,rcx
代码分析
依然来手工模拟一遍:
rax = 0110b (6)
rdx = 1101b (13)
rcx = rax & rdx = 0100b
rax = rax ^ rdx >> 1 = 1011b >> 1 = 0101b
rax = rax + rcx = 1001b (9) = (6+13)/2
直接求平均数:
rax + rdx = 10011 >> 1 = 1001
第一段操作把两个数之间相同的位提取出来,也就是相加需要进位的位
第二段操作把两个数之间不同的位提取出来并右移一位,也就是把非进位的位右移一位
因为要进位的位并不影响求取平均值进行右移1位的结果,所以最后相加的结果是两数的平均数,并且因为要把进位的位加到原来的数中去,需要将进位的位左移1位,因为原来的数右移1位了,所以也就可以直接相加了
测试代码:
.code
main proc
lea rax, [6]
lea rdx, [4]
mov rcx,rax ;rcx = rax
and rcx,rdx ;rcx = rcx & rdx = rax & rdx
xor rax,rdx ;rax = rax ^ rdx
shr rax,1 ;rax = rax >> 1 = rax ^ rdx >> 1
add rax,rcx ;rax = rax + rcx = (rax & rdx) + (rax ^ rdx >> 1)
ret
main ENDP
END