我需要对7位值进行任意重新排序(是的,我知道我应该使用表格),并且想知道是否有任何一点黑客可以做到这一点。
示例:
// <b0, b1, b2, b3, b4, b5, b6> -> <b3, b2, b4, b1, b5, b0, b6>
// the naive way
out =
(0x020 & In) << 5 |
(0x008 & In) << 2 |
(0x040 & In) |
(0x012 & In) >> 1 |
(0x004 & In) >> 2 |
(0x001 & In) >> 3;
// 6 ANDs, 5 ORs, 5 shifts = 16 ops
编辑: 我在思考this
的内容只是为了踢,因为我是AFTK,我正在尝试蛮力搜索形式的解决方案:
((In * C1) >> C2) & 0x7f
找不到解决方案。
答案 0 :(得分:5)
第一步似乎是了解数学解决方案并对其进行优化。
答案 1 :(得分:4)
看看你的“天真”代码的编译器输出,它可能会让你感到惊讶。我曾经做过类似的事情并且编译器(VC ++ 2005)完全改变了所有ands的值并为我移动以使它们更有效,例如我确定它会删除你的“(0x001&amp; In)&gt ;&gt; 3“。
但是,是的,如果重新洗牌是一个固定的功能,那么表格可能是最好的。
<强>更新强>
笑一笑,我看了VC ++ 2005的编译器输出......
首先我为“In”尝试了一个常量值,但是编译器没有被愚弄,它产生了这个代码:
mov eax,469h
即。它彻底优化了它。
所以...我尝试了一个正确的输入并得到了这个:
00401D4F mov eax,ecx
00401D51 and eax,20h
00401D54 shl eax,3
00401D57 mov edx,ecx
00401D59 and edx,8
00401D5C or eax,edx
00401D5E mov edx,ecx
00401D60 sar edx,1
00401D62 and edx,2
00401D65 or edx,ecx
00401D67 sar edx,1
00401D69 shl eax,2
00401D6C and edx,9
00401D6F or eax,edx
00401D71 and ecx,40h
00401D74 or eax,ecx
这是四个班次操作,五个AND,四个OR - 对六个输入来说不错。可能比大多数人手工做的要好。
它可能也针对无序执行进行了优化,因此它的时钟周期将比看起来少。 : - )
答案 2 :(得分:2)
有许多用于常见操作的比特错误的黑客攻击,即反转32位字中的位的顺序(每个移位10,AND和OR,AFAICR)。
在这种情况下,从输入到输出的显然是完全任意的映射,我看不到任何清理它的方法。
使用查找表:)
答案 3 :(得分:0)
在优化之前,你应该确保你的'天真'方式正在做你想要的。如果我把你的代码变成一个函数并运行这个循环:
for (b=0;b<7;b++)
{
i=1<<b;
printf("%d: %02x -> %02x\n", b, i, shuffle(i));
}
它产生此输出,与注释相矛盾。事实上,它失去了一些东西。
0: 01 -> 00
1: 02 -> 01
2: 04 -> 01
3: 08 -> 20
4: 10 -> 08
5: 20 -> 00
6: 40 -> 40
为了得到你描述的洗牌,我会像这样编码:
// 0 1 2 3 4 5 6
//-> 3 2 4 1 5 0 6
(0x001 & In) << 3 |
(0x004 & In) << 2 |
(0x020 & In) |
(0x012 & In) << 1 |
(0x008 & In) >> 2 |
(0x020 & In) >> 5 ;