当编译器从c ++代码创建完全相同类型的指令时,为什么不编译此代码

时间:2014-09-16 14:55:34

标签: c++ assembly inline-assembly

考虑以下代码

int a = 10;
int b = 2;
int c = 0;

int asmdivide(void);

int main(int argc, char* argv[])
{

     c = a / b;
    asmdivide();
    return 0;
}

int asmdivide()
{
    __asm

    {
        push dword ptr[a]
        push dword ptr[b]
        pop ecx
        idiv ecx, dword ptr[a] //causes compile error
        push ecx
        pop dword ptr[c]
    }
    return c;
}

为什么这一行idiv ecx, ds:dword ptr[a] //causes compile error当编译器从这一行生成这条指令idiv eax,dword ptr ds:[1308004h]时会导致编译错误`int b = 2;

输出的错误是

error C2414: illegal number of operands

请参阅下面的屏幕截图,了解装配输出

Assembly Output

我正在使用Visual Studio 2013。 任何解释都会被重视

1 个答案:

答案 0 :(得分:5)

看起来您的代码和反汇编可能是相同的,但这仅仅是调试器选择显示反汇编的原因。

IDIV的红利是隐含的,在除以32位值(实际为EAX)时始终为EDX:EAX。引用英特尔手册:

F7 /7    IDIV r/m32   M   Valid   Valid   Signed divide EDX:EAX by r/m32, with result
                                          stored in EAX ←Quotient, EDX ←Remainder.

因此,您尝试将另一个寄存器指定为被除数将失败。

您只能为IDIV指定除数,如:

cdq                 ; sign-extend eax into edx:eax
idiv dword ptr [a]  ; divide edx:eax by [a]