visual-c++ - VC++ SSE 代码生成 - 这是编译器错误吗?

标签 visual-c++ assembly x86 sse visual-studio-debugging

VC++ 中的一个非常特殊的代码序列生成了以下指令(针对 Win32):

unpcklpd    xmm0,xmmword ptr [ebp-40h]

出现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;
    }

如果您愿意,可以从 here 下载带有所有开关设置的现成 vcxproj。 .这也包括完整的 ASM。

最佳答案

更新:现在是 confirmed VC++ compiler bug ,希望在 VS2015 RTM 中得到解决。

编辑:连接报告,像许多其他报告一样,现在是垃圾。然而,编译器错误似乎在 VS2017 中得到解决——而不是在 2015 年更新 3 中。

关于visual-c++ - VC++ SSE 代码生成 - 这是编译器错误吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28981458/

相关文章:

c++ - Win32 C++ 重绘窗口

c++ - Main 方法与教程中的不同

assembly - 如何使用重复的字节值填充 64 位寄存器

c - 堆栈上的 "missing"空间是做什么用的?

assembly - 如何将较小的值弹出到寄存器中

c++ - 在 VC++ 中跨函数调用使用双指针进行操作

c++ - 我应该使用全局变量还是每次都调用该函数? C++

assembly - 为什么我们在 CMPXCHG 之前需要锁定前缀

assembly - 在 Linux 中哪些寄存器不受用户空间的影响?

从 x86 汇编语言调用 C 函数