2014-09-16 2 views
0

Рассмотрим следующий кодПочему этот код не компилируется, когда компилятор создает точно такой же тип команды из C++ кода

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. Любое объяснение будет цениться

+0

Еще не компилировать с той же ошибкой –

ответ

5

Это может показаться, что ваш код и разборка одинаковы, но это только из-за того, как отладчик ch ooses для демонстрации разборки.

Дивиденция для IDIV неявная и всегда равна EAX при делении на 32-разрядное значение (фактически EDX:EAX). Чтобы процитировать руководство Intel:

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] 
+0

Так что правильный способ написания этой инструкции –

+0

Чтобы указать только один операнд (который будет делителем). Я добавил пример. – Michael

+0

Спасибо, что работает, как я и ожидал сейчас. Знаете ли вы, почему это было сделано так? –

Смежные вопросы