汇编 x86 "PSHUFB 128bit" 另一种语言的实现

Assembly x86 "PSHUFB 128bit" implementation in another language

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

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' 将浮点数更改为十六进制:

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

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

之前

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 它从哪里来?

它的工作方式类似于 16 个并行 table 查找,对设置了最高位的索引进行特殊处理。因此,例如,它可能看起来像这样:(未测试,不是 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个并行赋值,即read-before-write,第二次查找不受to中发生的事情影响第一个字节等等。英特尔的代码片段隐含了这一点(或者是错误的,取决于你如何看待它)。