Ofe*_*lon 5 x86 assembly sse visual-c++ visual-studio-debugging
VC++中一个非常特殊的代码序列生成了以下指令(对于Win32):
unpcklpd xmm0,xmmword ptr [ebp-40h]
Run Code Online (Sandbox Code Playgroud)
出现2个问题:
(1)据我了解intel手册,unpcklpd接受128对齐的内存地址作为第二个参数.如果地址相对于堆栈帧,则不能强制对齐.这真的是一个编译器错误吗?
(2)只有在从调试器运行时才会执行此指令时抛出异常,即使这样也不总是如此.即使附加到进程并执行此代码也不会抛出.怎么会这样??
抛出的特殊异常是0xFFFFFFFF处的访问冲突,但是AFAIK只是一个未对齐的代码.
[编辑:]这里有一些来源证明代码生成错误 - 但通常不会导致崩溃.(这主要是我想知道的)
[编辑2:]代码示例现在重现实际崩溃.这个也在调试器外崩溃 - 我怀疑是因为调试器在不同的典型基地址启动程序而产生差异.
// mock.cpp
#include <stdio.h>
struct mockVect2d
{
double x, y;
mockVect2d() {}
mockVect2d(double a, double b) : x(a), y(b) {}
mockVect2d operator + (const mockVect2d& u) {
return mockVect2d(x + u.x, y + u.y);
}
};
struct MockPoly
{
MockPoly() {}
mockVect2d* m_Vrts;
double m_Area;
int m_Convex;
bool m_ParClear;
void ClearPar() { m_Area = -1.; m_Convex = 0; m_ParClear = true; }
MockPoly(int len) { m_Vrts = new mockVect2d[len]; }
mockVect2d& Vrt(int i) {
if (!m_ParClear) ClearPar();
return m_Vrts[i];
}
const mockVect2d& GetCenter() { return m_Vrts[0]; }
};
struct MockItem
{
MockItem() : Contour(1) {}
MockPoly Contour;
};
struct Mock
{
Mock() {}
MockItem m_item;
virtual int GetCount() { return 2; }
virtual mockVect2d GetCenter() { return mockVect2d(1.0, 2.0); }
virtual MockItem GetItem(int i) { return m_item; }
};
void testInner(int a)
{
int c = 8;
printf("%d", c);
Mock* pMock = new Mock;
int Flag = true;
int nlr = pMock->GetCount();
if (nlr == 0)
return;
int flr = 1;
if (flr == nlr)
return;
if (Flag)
{
if (flr < nlr && flr>0) {
int c = 8;
printf("%d", c);
MockPoly pol(2);
mockVect2d ctr = pMock->GetItem(0).Contour.GetCenter();
// The mess happens here:
// ; 74 : pol.Vrt(1) = ctr + mockVect2d(0., 1.0);
//
// call ? Vrt@MockPoly@@QAEAAUmockVect2d@@H@Z; MockPoly::Vrt
// movdqa xmm0, XMMWORD PTR $T4[ebp]
// unpcklpd xmm0, QWORD PTR tv190[ebp] **** crash!
// movdqu XMMWORD PTR[eax], xmm0
pol.Vrt(0) = ctr + mockVect2d(1.0, 0.);
pol.Vrt(1) = ctr + mockVect2d(0., 1.0);
}
}
}
void main()
{
testInner(2);
return;
}
Run Code Online (Sandbox Code Playgroud)
如果您愿意,可以从这里下载一个准备好的vcxproj,其中包含所有开关.这也包括完整的ASM.
更新:现在这是一个已确认的 VC++ 编译器错误,希望在 VS2015 RTM 中得到解决。
编辑:连接报告和许多其他报告一样,现在是垃圾。然而,编译器错误似乎在 VS2017 中得到了解决 -而不是在 2015 年更新 3 中。