【发布时间】:2016-12-25 11:24:01
【问题描述】:
我正在尝试使用 32 位操作系统上的 XMM0 128 位寄存器从 char 指针数组加载/存储内存。
我尝试的很简单:
int main() {
char *data = new char[33];
for (int i = 0; i < 32; i++)
data[i] = 'a';
data[32] = 0;
ASM
{
movdqu xmm0,[data]
}
delete[] data;
}
问题是这似乎不起作用。第一次调试得到的Win32应用程序:
xmm0 = 0024F8380000000000F818E30055F158
第二次调试我得到了:
xmm0 = 0043FD6800000000002C18E3008CF158
所以这行一定有什么东西:
movdqu xmm0,[data]
我尝试改用这个:
movdqu xmm0,data
但我得到了相同的结果。
我认为问题在于我复制了地址而不是地址处的数据。但是xmm0 寄存器中显示的值对于 32 位地址来说太大了,所以它必须从另一个地址复制内存。
我还尝试了一些在互联网上找到的其他说明,但结果相同。
是我传递指针的方式还是我对 xmm 基础知识有误解?
我们将不胜感激。
即使我找到了解决方案(终于在三个小时后),我仍然想要一个解释:
ASM
{
push eax
mov eax,data
movdqu xmm0,[eax]
pop eax
}
为什么要将指针传递给 32 位寄存器?
【问题讨论】:
-
注意
data是一个指针。 -
您能否尝试一下是否可以直接使用局部变量
char data[33];而不是带有指针的new/delete,就像在[data]的原始帖子中一样?我现在无法调试,但我认为这可能有效,因为我可以想象编译的源代码。目前让我感到困惑的是,C++ 与char *data的区别是什么。从 C++ 的角度来看,它们看起来是等价的。我可能忽略了一些东西。 (在第二个版本中,mov eax,data被编译为mov eax,[data],对吧?) -
x86 没有“内存间接”寻址模式。您正在将指针加载到
xmm0。由于xmm0比指针大,因此您也在读取内存中超出指针存储位置的垃圾字节。 -
它适用于非指针。是的,它被编译为 mov eax,[data] (Ped7g)。嗯,装配时实际上是什么“数据”?也许我误解了 ASM 如何威胁“数据”。我认为“数据”受到威胁,因为它在 C++ 中受到威胁。它似乎将“数据”变量的指针返回到“数据”指针地址,而不是像在 C++ 中那样。这个解释在我看来是合乎逻辑的
-
推荐的方法是
mm_loadu_si128内在函数。
标签: c++ assembly sse cpu-registers