装配x86" PSHUFB 128bit"用另一种语言实现

时间:2015-03-03 17:02:34

标签: python algorithm assembly x86 hex

我正在撤销一些应用程序,我遇到了这个操作码:

PSHUFB XMM2, XMMWORD_ADDRESS

我尝试在python中实现此函数的算法但没有成功! 这个操作码应该如何工作的参考是: http://www.felixcloutier.com/x86/PSHUFB.html

以下是代码段:

PSHUFB (with 128 bit operands)

    for i = 0 to 15 {
         if (SRC[(i * 8)+7] = 1 ) then
              DEST[(i*8)+7..(i*8)+0] ← 0;
          else
              index[3..0] ← SRC[(i*8)+3 .. (i*8)+0]; DEST[(i*8)+7..(i*8)+0] ← DEST[(index*8+7)..(index*8+0)];
         endif
    }
DEST[VLMAX-1:128] ← 0

我试图实现此操作码的128版本但没有成功。 以下是函数

之前和之后的值

之前

WINDBG>r xmm2
xmm2=           0 3.78351e-044 6.09194e+027 6.09194e+027

WINDBG>r xmm2
xmm2=9.68577e-042            0 4.92279e-029 4.92279e-029

在python中你可以使用'struct'将那些从float数字改为Hex:

hex(struct.unpack('<I', struct.pack('<f', f))[0])

所以我可以说这些是 PSHUFB 操作码之前和之后 XMM2 的十六进制值:

之前

xmm2 = 0 0x0000001b 0x6d9d7914 0x6d9d7914

xmm2 = 00001b00 00000000 10799d78 10799d78

最重要的是,我差点忘了.. XMMWORD_ADDRESS 的价值是:

  

03 02 01 00 07 06 05 04 0D 0C 0B 0A 09 08 80 80

     

xmmword 808008090A0B0C0D0405060700010203h

可以高度赞赏Python中的实现。 C中的实现也可以起作用

或者可能解释它是如何运作的! 因为我无法理解英特尔的参考资料

这是我到目前为止的代码算法

x = ['00', '00', '00', '00', '00', '00', '00', '1b', '6d', '9d', '79', '14', '6d', '9d', '79', '14']
s = ['03', '02', '01', '00', '07', '06', '05', '04', '0D', '0C', '0B', '0A', '09', '08', '80', '80']
new = []
for i in range(16):
    if 0x80 == int(s[i], 16) & 0x80:
        print "MSB", s[i]
        new.append(0)
    else:
        print "NOT MSB", s[i]
        new.append( x[int(s[i], 16) & 15] )

print x
print new

其中x是xmm0,s是SRC。

我得到的输出是:

  

['00','00','00','00','00','00','00','1b','6d','9d','79',   '14','6d','9d','79','14']

     

['00','00','00','00','1b','00','00','00','9d','6d','14',   '79','9d','6d','00','00']

我应该去哪里

  

['00','00','1b','00','00','00','00','00','10','79','9d',   '78','10','79','9d','78']

我现在注意到的其他东西,在'output'中我得到十六进制数0x78 它可能来自哪里?

1 个答案:

答案 0 :(得分:2)

它的工作方式类似于16个并行表查找,对具有最高位设置的索引进行特殊处理。例如,它看起来像这样:(未经过测试,而不是Python)

for (int i = 0; i < 16; i++)
    new_dest[i] = (src[i] & 0x80) ? 0 : dest[src[i] & 15];
dest = new_dest;

new_dest有重大意义,因为它实际上是16个并行分配,即先读后读,第二次查找不会受到发生的事情的影响第一个字节,依此类推。英特尔的代码片段会隐含(或者错误,取决于您如何看待它)。