【发布时间】:2016-09-29 21:02:26
【问题描述】:
我想在汇编中编写一个快速整数平方根算法,它需要无符号的 32 位。我一直在阅读this,并有了一个想法。这是我的伪代码:
res <- 0
for i from 15 downto 0 do:
change the ith bit of result to 1
if res^2 > x then:
change the ith bit of res back to 0
return res
到目前为止,我已经完成了:
sqrt:
movl $0, %eax
movl $15, %edx
jmp .L8
.L9
.L8
cmpq cmpq $0, %edx
jge .L9
我被困在 for 循环操作中,更改第 i 位并进行移位。我也不想使用除法或 sqrt 指令。我知道我可能应该使用shr,但我不知道从哪里开始或如何做。如何在 for 循环中进行操作?我从哪里开始?
【问题讨论】:
-
shr and similar 到底有什么问题?像往常一样设置和清除位:使用 OR 和 AND 掩码。
-
我的问题是,如果我得到一个整数(例如将 x 设置为 20),我应该如何将其转换为二进制并使用 shift 遍历位?
-
数字就是数字,二进制只用于想或记下一个数字。你不需要转换任何东西。 Google for AND, OR, SHIFT 你会发现大量的材料。
-
您可能不会击败硬件双精度平方根指令(Intel Skylake:15-16 周期延迟,吞吐量为每 4-6 个周期一个)。
double可以精确地表示每个整数,因此唯一的技巧是将 unsigned 整数转换为double。这在 64 位模式下很容易:只需将零扩展到 64 位并使用CVTSI2SD xmm0, rax,因为每个无符号 32 位整数都适合一个有符号 64 位整数。在 32 位代码中,it takes some work,但还不错。 -
对于 64 位整数,x87 80 位浮点数可以精确地表示每个 有符号 整数。不过,我认为您可能对无符号 64 位有问题。我认为尾数大小对于每个整数来说太小了,无法以 80 位(长双精度)精确表示。 (还要注意,即使在 32 位模式下,您也可以使用 x87 FILD 与 64 位整数进行转换,并且 x87 FSQRT 并不比 SSE2 SQRTSD 慢多少)。