selph
selph
发布于 2022-01-21 / 358 阅读
0
0

《xchg rax,rax》片段分析0x14--求平均值

前言

本次是该系列的的第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

评论