XMM 寄存器指令及其 C 等效项

逆向工程 x86 漂浮
2021-06-27 15:51:38

我正在尝试将一些 x86 程序集转换回 C++,但我无法弄清楚这组指令最初是如何编写的。

movd xmm0,eax ; byte read from device '0x04'
cvtdq2pd xmm0,xmm0 ; convert packed to double?
shr eax,0x1F ; highest bit
addsd xmm0,qword ptr ds:[eax*8+0x4F6CC0] ; global [0, 4294967296] if I read it right
cvtpd2ps xmm0,xmm0 ; double to packed?
movss dword ptr ds:[ebx+0x34],xmm0 ; store the result

我已经编译器资源管理器尝试了各种形式的转换floatdouble其他数据类型,但我找不到任何可以复制指令的内容。cvtdq2pdcvtpd2ps

上面的代码在 c/c++ 中会是什么样子,结果数据类型是什么?

1个回答

您可能不会得到精确的复制,因为cvtdq2pd需要第二个操作数的低 64 位,但由于我们在eax这里使用而限制为 32 位,因此可能有更好的(?)指令可以使用。

cvtsi2sd xmm0, eax

会做同样的事情

movd xmm0,eax

cvtdq2pd xmm0,xmm0

请参阅此处https://www.felixcloutier.com/x86/CVTDQ2PD.htmlhttps://www.felixcloutier.com/x86/CVTSI2SD.html

所以它真正做的是将 32 位有符号整数值转换为双精度浮点数。


关于你的实际问题:

cvtpd2ps xmm0,xmm0 ; double to packed?

CVTPD2PS xmm1, xmm2/m128

将 xmm2/mem 中的两个压缩双精度浮点值转换为 xmm1 中的两个单精度浮点值。

这会将xmm0[0:63]&处的两个双精度浮点数打包xmm0[64:127]到 的低 64 位xmm0,将它们从双精度浮点值转换为单精度浮点值 ( xmm0[0:31]& xmm0[32:63])。

参考:https : //www.felixcloutier.com/x86/CVTPD2PS.html

因此,如果xmm0表示 a的低 64 位double,则它现在已转换为 32 位浮点数,现在位于xmm0.

movss dword ptr ds:[ebx+0x34],xmm0

MOVSS xmm2/m32, xmm1

将标量单精度浮点值从 xmm1 寄存器移动到 xmm2/m32。

现在存储来自xmm0[0:31]into的 4 字节结果[ebx+0x34],我们知道这是float来自cvtpd2ps操作结果的单精度

所以这个操作的结果是一个 32 位的float

参考:https : //www.felixcloutier.com/x86/MOVSS.html


这里的代码应该是一个合理的近似值。在 Godbolt 中,它为我提供了与您所拥有的类似的组件。

double* d_arr = (double*)0x4F6CC0;

int main() {

    int in = 4;
    int signbit = ((unsigned int)in >> 31);
    float result = *(double*)(d_arr + signbit) + in;
    return 0;
}

结论:

cvtdq2pd&cvtpd2ps对于这里实际计算的内容来说太强大了。除非我完全读错了,否则 的高 64 位xmm0永远不会与结果相关。

免责声明:

我以前从未使用过浮点汇编。我现在只是查阅了文档。我可能会遗漏一些东西。