Подтвердить что ты не робот

X86 Разница в инструкциях CMP

Вопрос

Какова (нетривиальная) разница между двумя инструкциями 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 byte-opcode:

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

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

10 de   adcb   %bl,%dh
12 f3   adcb.s %bl,%dh

Ответ 3

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