前言
本次是该系列的的第0x13篇,本篇介绍了另一种新的两数相加的方法,应该可以算是另一种加法的原理
实验环境:
- Windows10 + VS2022 + masm
0x13
代码片段链接:xorpd | xchg rax,rax 0x13
mov rcx,0x40
.loop:
mov rdx,rax
xor rax,rbx
and rbx,rdx
shl rbx,0x1
loop .loop
代码分析
手工模拟一下过程:
rax 1100b
rbx 0110b
第一轮:
rdx = 1100b //
rax = 1010b // 取出rax和rbx里不用计算进位的项
rbx = 0100b // 取出rax和rbx里需要进行进位的项
rbx = 1000b // 将进位的项左移一位,变成进位后的值
rax 1010b
rbx 1000b
第二轮:
rdx = 1010b
rax = 0010b // 将进位后的值和未进行进位的值进行相加,取出不用计算进位的项
rbx = 1000b // 取出当前需要进位的项
rbx = 10000b// 将进位的项左移一位,变成进位后的值
rax 00010b
rbx 10000b
第三轮:
rdx = 00010b
rax = 10010b // 再次将进位后的值和未进位的值进行相加,取出不用计算进位的项
rbx = 00000b // 再次取出当前需要进位的项
rbx = 00000b // 再次将进位的项左移一位,变成进位后的值
第四轮:结果未改变 // 直到需要进位的项为0时,结果不再发生变化,循环结束
结果是10010b // 结果是两数之和
这里每一轮循环都对rax进行和rbx的异或操作,然后rbx左移一位
当rbx为0时,后面的循环不会造成结果发生任何变化
最后的结果是两数相加的和
测试代码:
.code
main proc
lea rax, [01110b]
lea rbx, [00110b]
xor rdi, rdi
mov rcx,040h ;rcx = 0x40 循环0x40(64)次,刚好对应64位
loopA:
mov rdx,rax ;rdx = rax
xor rax,rbx ;rax = rax ^ rbx
and rbx,rdx ;rbx = rbx & rdx
shl rbx,01h ;rbx = rbx * 2,一共会左移64次,每一位都进行了一遍这样的运算
inc rdi ;计算循环次数
cmp rbx,0
je endA
loop loopA
endA:
ret
main ENDP
END
中划线