前言
本次是该系列的的第0x22篇,昨天小病一场,现在深刻体会到健健康康才是真,以健康为代价换取什么都不值,要健健康康的珍惜当下!(今天把昨天该更的补上!)
实验环境:
- Windows10 + VS2022 + masm
0x22
代码片段链接:xorpd | xchg rax,rax 0x22
mov rdx,0xaaaaaaaaaaaaaaab
mul rdx
shr rdx,1
mov rax,rdx
代码分析
mul指令,这里的mul rdx
功能是计算rax * rdx
,结果是保存在rdx:rax
里,rdx保存高位数据,rax保存低位数据(该指令会修改rdx寄存器,刚刚知道这个小细节)
测试代码:
.code
main proc
mov rax, 30
mov rdx,0aaaaaaaaaaaaaaabh
mul rdx ;mul指令结果保存在rdx:rax,rdx保存高位数据
shr rdx,1 ;rdx高位数据右移一位
mov rax,rdx
ret
main ENDP
END
当输入rax=1
时,rdx:rax=0:AAAAAAAAAAAAAAAB
,输出:0
当输入rax=2
时,rdx:rax=1:5555555555555556
,输出:0
当输入rax=3
时,rdx:rax=2:0000000000000001
,输出:1
当输入rax=4
时,相当于计算完rax=3
后把rax=3
的结果进行输入,得到两个值的和:1+0=1
从输入和输出的结果上来看,功能是:rax = rax / 3
向下取整
而这个魔数0xAAAAAAAAAAAAAAAB * 3的倍数
时,都会刚刚好64位溢出之后保留一个很小的整数,例如0xAAAAAAAAAAAAAAAB*3 = 1
,溢出的高位则是2,从结果的关系上来看,溢出的高位与rax/3
的值,是右移一位的关系
所以本例介绍了一种不用除法指令计算除法的方式,经查阅资料,这是一种除法变乘法的常见优化操作