Разница в инструкциях 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.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

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


person Pindatjuh    schedule 03.05.2010    source источник


Ответы (2)


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

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

person interjay    schedule 03.05.2010
comment
Эти 1-битные степени свободы также обеспечивают скрытый канал для компиляторов, чтобы позвонить домой — они могут помечать водяными знаками создаваемые ими двоичные файлы, а поставщик компилятора может попросить вас объяснить, если они найдут ваше программное обеспечение со своим водяным знаком, но без лицензии на файл. - person Bernd Jendrissek; 14.05.2010

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

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

10 de   adcb   %bl,%dh
12 f3   adcb.s %bl,%dh
person phuclv    schedule 15.11.2013