为什么是16位注册使用暂指令在这个代码?
-
10-07-2019 - |
题
在 这条铁杆 有一个功能 find_maskwidth()
这基本上检测所需的比特数量来表示 itemCount
dictinct值:
unsigned int find_maskwidth( unsigned int itemCount )
{
unsigned int maskWidth, count = itemCount;
__asm {
mov eax, count
mov ecx, 0
mov maskWidth, ecx
dec eax
bsr cx, ax
jz next
inc cx
mov maskWidth, ecx
next:
}
return maskWidth;
}
问题是他们为什么使用 ax
和 cx
寄存器而不是的 eax
和 ecx
?
解决方案
我只能猜测,他们希望永远只能处理的领域,没有超过16位。因为它被用来确定的比特数,可以用来报告这样的事情的核心数或逻辑处理器在一个包它可能会是一个同时溢出前述65535.
我只是希望有人不能决定使用程序成为一个更一般的目的。
只是一个供参考-如果你想要做这样的事情不放弃x86会(虽然我想对该文章的目的,正在非便携式是相当多的定), 点摆弄黑客网页 有你复盖。
其他提示
我猜测的原始数据只是16位宽。由于cx到了一位数,没有机会,它可大于一个非常小的数目无论如何。
它们感兴趣地注意到,在一个级别的操作码为16位和32位ia32指示是相同的,除了为前缀字节,因此,它是更有效的问题所有32个或所有16位的指令,这取决于哪个模式。我想这就是为什么你问的问题...
鉴于这个代码是真的真的生病写入(有的是完全没有必要为maskWidth和数变量,例如,除了使码混乱)我猜你可以放心,它只是另一种"坏事"在这个代码。
常规bascially确定的二进制(两个基)对数itemCount.
它将提供完全错误的价值观,如果itemCount>2^16.它不饱和或什么的,它只是简单的错误。输入参数"unsigned int",这使得它更是错误的。因此,它将停止工作在更65536核心。
我的猜测是,有人在英特尔挖了一些非常古老的代码,可追溯到16位的时间没有真正理解它,并且使用它,因为65536将能够永远,正是因为640k存储器将足够永远或者作为两位数的年份数字就足够了,直到结束的时间。
我要说这是因为提交人的这种代码很可能真的不知道他在做什么:-).16位的版本的这些说明是更长的时间,并没有任何速度更快。事实上,他们可能会导致部分登记的摊位上的下一个指令,使用ECX(即该章).
还注意到,跳可以安全移的一个指令前后(DEC),作为DEC已经设置苏时,其输出是零。这可以简化码的一点。
因此,这是我怎么会写这段代码:
mov eax, [count]
xor ecx, ecx
dec eax
jz next
bsr ecx, eax
inc ecx
next:
mov [maskWidth], ecx
此外,该动机下降到大会这里,似乎是采用的暂指令,该指令没有任何相当于在C语言或图书馆。你可以避免使用会通过使用一个编译器特征的功能,用于这一目的。虽然这些都是固有的产品,也不是联大会。
在海湾合作委员会等同功能看起来是这样的:
unsigned int find_maskwidth(unsigned int itemCount)
{
if(itemCount <= 1)
return 0;
else
return 32 - __builtin_clz(itemCount - 1);
}
更具可读性,不是吗?