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

标签 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]//导致编译错误 当编译器生成这条指令时导致编译错误 idiv eax,dword ptr ds:[ 1308004h]从这一行`int b = 2;

输出的错误是

error C2414: illegal number of operands

汇编输出请看下面的截图

Assembly Output

我正在使用 Visual Studio 2013。 任何解释都将受到重视

最佳答案

看起来您的代码和反汇编是一样的,但这只是由于调试器选择如何显示反汇编。

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] 

关于c++ - 为什么当编译器从 C++ 代码创建完全相同类型的指令时,此代码无法编译,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25872084/

相关文章:

c++ - 排序算法问题 - 模板

c++ - 零和一的二维数组

linux - 将整数添加到缓冲区 nasm 的语法

assembly - AVR 微架构如何能够仅在 1 个时钟周期内从 GP 寄存器获取 2 个操作数到 ALU?

.net - 类型为 'System.Reflection.TargetParameterCountException' 的未处理异常

assembly - masm 程序生成的 .lst 文件的内容是什么?

c++ - 如何在 ASM 中创建循环?

c++ - 以下内联汇编有什么问题?

GCC 内联汇编器 "memory"Clobber 不会阻止重新排列 ARM 中的代码

c++ - 为什么设置套接字发送/接收缓冲区大小大于 sysctl max 时没有错误?