Почему важен порядок аргументов в инструкции cmp? - PullRequest
1 голос
/ 19 мая 2019

Интересно, почему cmp инструкция требует определенного условия для порядка аргументов.

Например, я попробовал оба из них.

  1. cmpl %eax, $'A'
  2. cmpl $'A', %eax

В первой строке возвращена ошибка, сообщающая о несоответствии типов операндов.Вторая линия работала хорошо.

Я изучил руководство по Intel IA-32, но оно не смогло ответить на мой вопрос.Он просто сказал вычитание между аргументами 1 и 2, а не то, какие типы должны иметь каждый аргумент.

Я хочу знать, почему первая строка кода вернула несоответствие типов операндов, а вторая строка - нет.

1 Ответ

4 голосов
/ 19 мая 2019

Инструкция машинного кода поддерживает только это направление немедленно. Если вы не нашли это, вы искали не в том месте. Руководство по Intel vol.2 подробно описывает каждую доступную кодировку для каждой инструкции. Вот HTML-фрагмент записи для cmp.


Помните, что ограничения сборки не являются произвольными вариантами исходного уровня; это не язык как C ++, это способ описания машинного кода.

Большинство инструкций ALU записывают свое назначение (особенно инструкции, относящиеся к оригинальному 8086), поэтому оно не может быть немедленным. например sub %eax, $123 явно не имеет смысла. Таким образом, согласованность форматов машинного кода / простота декодирования является одной из причин отсутствия специального кода операции cmp с непосредственным «назначением». Это также будет нерегулярно для синтаксиса ассемблера, если ассемблеры отобразят этот код операции к той же cmp мнемонике вместо другой мнемоники reverse-cmp.

Напротив, cmp r/m32, r32 и cmp r32, r/m32 существуют, поэтому вы можете сравнить память с регистром в любом направлении. Опять же, это согласуется с шаблонами других инструкций ALU, таких как add и sub, так что это также имеет смысл для более «регулярного» декодирования / шаблонов в машинном коде.

Если вы переходите на результат с помощью jcc, вы всегда можете поменять местами операнды и использовать противоположное условие. Иногда вы хотите, чтобы CF устанавливал определенный способ кормления adc или sbb, хотя да, иногда это доставляет неудобства.

Но это не было достаточной причиной для того, чтобы архитектор набора команд 8086, Стивен Морс, использовал один из немногих неиспользованных кодов операций для обратного сравнения с немедленным кодированием cmp.


Что могло бы иметь смысл, так это команда обратного вычитания или обратного сравнения, например, ARM имеет (т. Е. dst = src - dst вместо dst -= src), но формат машинного кода переменной длины x86 означает, что только так много 1-байтовых кодов операций. Это могла быть просто еще одна «нормальная» немедленная инструкция ALU.

Или на самом деле еще 5 кодов операций, включая 2 выделенных байта, если мы следуем шаблону нормальных инструкций ALU: нормальные op r/m8, imm8, op r/m16, sign_extended_imm8, op r/m16, imm16 и AL, imm8 и AX, imm16 короткие формы (без ModRM байт). Я предполагаю, что для не непосредственных операндов мнемоника может быть псевдонимом для cmp с операндами в обратном порядке, поэтому нам также не нужны эти 4 кода операции (8 и 16-битные в обоих направлениях).

ARM появился позже и использовал 32-битное командное слово фиксированной ширины, поэтому было достаточно места для кодирования кода операции, которое можно было использовать в таких полезных инструкциях, как обратное сравнение и обратное вычитание.

...