您可能不会得到精确的复制,因为cvtdq2pd需要第二个操作数的低 64 位,但由于我们在eax这里使用而限制为 32 位,因此可能有更好的(?)指令可以使用。
cvtsi2sd xmm0, eax
会做同样的事情
movd xmm0,eax
cvtdq2pd xmm0,xmm0
请参阅此处https://www.felixcloutier.com/x86/CVTDQ2PD.html和https://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永远不会与结果相关。
免责声明:
我以前从未使用过浮点汇编。我现在只是查阅了文档。我可能会遗漏一些东西。