x86 CMP инструкция разница - PullRequest
12 голосов
/ 03 мая 2010

Вопрос

В чем (нетривиальная) разница между следующими двумя инструкциями x86?

39 /r    CMP r/m32,r32   Compare r32 with r/m32
3B /r    CMP r32,r/m32   Compare r/m32 with r32

Фон

Я создаю Java-ассемблер, который будет использоваться промежуточным языком моего компилятора для создания исполняемых файлов Windows-32.

В настоящее время у меня есть следующий код:

final ModelBase mb = new ModelBase(); // create new memory model
mb.addCode(new Compare(Register.ECX, Register.EAX)); // add code
mb.addCode(new Compare(Register.EAX, Register.ECX)); // add code

final FileOutputStream fos = new FileOutputStream(new File("test.exe"));
mb.writeToFile(fos);
fos.close();

Для вывода корректного исполняемого файла, который содержит две инструкции CMP в TEXT-разделе. Исполняемый файл, выведенный в «text.exe», ничего интересного не сделает, но это не главное. Класс Compare является оболочкой для инструкции CMP.

Приведенный выше код выдает (проверка с помощью OllyDbg):

Address   Hex dump                 Command
0040101F  |.  3BC8                 CMP ECX,EAX
00401021  |.  3BC1                 CMP EAX,ECX

Разница невелика: если я использую 39 байт-код операции:

Address   Hex dump                 Command
0040101F  |.  39C1                 CMP ECX,EAX
00401021  |.  39C8                 CMP EAX,ECX

Что заставляет меня задуматься об их синонимичности и о том, почему это вообще существует.

Ответы [ 3 ]

19 голосов
/ 04 мая 2010

Неважно, какой код операции вы используете, если вы сравниваете два регистра. Единственное отличие заключается в сравнении регистра с операндом памяти, поскольку используемый код операции определяет, какой из которых будет вычтен.

Что касается того, почему это существует: формат инструкции x86 использует байт ModR / M для обозначения либо адреса памяти, либо регистра. Каждая инструкция может иметь только одно значение ModR / M, что означает, что она может получить доступ только к одному адресу памяти (не включая специальные инструкции, такие как MOVSB). Таким образом, это означает, что не может быть общей инструкции cmp r/m32, r/m32, и нам нужны два разных кода операции: cmp r/m32, r32 и cmp r32, r/m32. Как побочный эффект, это создает некоторую избыточность при сравнении двух регистров.

3 голосов
/ 15 ноября 2013

Это избыточность x86 . Подобных случаев гораздо больше. Компилятор / ассемблер может использовать любой из действительных кодов операций

Какой-то ассемблер позволяет вам выбрать, какой код операции выдавать. Например, на GAS вы можете прикрепить «.s», чтобы использовать другую кодировку команд

10 de   adcb   %bl,%dh
12 f3   adcb.s %bl,%dh
2 голосов
/ 04 мая 2010

CMP ECX, EAX - это ECX-EAX и CMP EAX, ECX - это EAX-ECX. Флаги устанавливаются по-разному в зависимости от того, какой операнд сравнивается с каким. Конечно, вы, вероятно, могли бы избежать неприятностей только с одним из них, если бы не структура mod / r-m инструкций x86.

...