(编辑:让我们称之为"测量可能出错的经验教训."我仍然没有弄清楚究竟是什么导致了这种差异.)
我在 Mark Crowne 找到了一个非常快速的整数平方根函数.至少在我的机器上使用GCC,它显然是我测试过的最快的整数平方根函数(包括来自标准库的Hacker's Delight,this page和floor(sqrt())中的函数.
清理格式化,重命名变量和使用固定宽度类型后,它看起来像这样:
static uint32_t mcrowne_isqrt(uint32_t val)
{
uint32_t temp, root = 0;
if (val >= 0x40000000)
{
root = 0x8000;
val -= 0x40000000;
}
#define INNER_ISQRT(s) \
do \
{ \
temp = (root << (s)) + (1 << ((s) * 2 - 2)); \
if (val >= temp) \
{ \
root += 1 << ((s)-1); \
val -= temp; \
} \
} while(0)
INNER_ISQRT(15);
INNER_ISQRT(14);
INNER_ISQRT(13);
INNER_ISQRT(12);
INNER_ISQRT(11); …Run Code Online (Sandbox Code Playgroud) 我已经读过如果可以修改eflags第18位(AC - 对齐检查),你知道CPU是486或更新.在386上,该位抵抗修改.
我从这个站点解除了以下汇编代码并添加了详尽的注释(保留了奇怪的语法):
asm
mov bx,sx ; Save the stack pointer to bx (is sx a typo or a real register?).
and sp,$fffc ; Truncate the stack pointer to a 4-byte boundary.
pushfl ; Push the eflags register to the stack.
pop eax ; Pop it into eax.
mov ecx,eax ; Save the original eflags value into ecx.
xor eax,$40000 ; Flip bit 18 in eax.
push eax ; Push eax to the stack.
popfl ; Pop …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用CPUID,但是附加了一些字符串.根据sandpile.org 的CPUID页面,CPUID标准函数0000_0004h及以上仅在MISC_ENABLE.LCMV标志设置为0时才起作用.该标志是模型专用寄存器(MSR)1A0的第22位.显然,这种限制是由于Windows NT中的一个错误(感谢让我更轻松,微软;)).
我可以使用CPUID 0000_0001h(ecx标志,位3)测试LCMV标志的存在.假设它存在,究竟是什么,为什么它对CPUID有这样的影响?MSR 1A0是读/写寄存器还是只读?这样的专用寄存器如何使用汇编代码读/写?
如果寄存器在技术上是读/写,那么在将CPU22指令恢复到原始设置之前,在将CPU22指令的持续时间内将第22位复位为0是否安全?或者如果它设置不正确(即启用),我几乎搞砸了?
最后,sandpile使用了"只有在MISC_ENABLE.LCMV设置为0时才启用此级别.这是由于Windows NT错误." 如果由于这个原因特别禁用了一堆标准级别,那么这是否会反映在CPUID级别0000_000h的eax寄存器(最大支持的标准级别)的输出中?
Phew ......我认为就是这样.