Сложение и вычитание в дополнении к двум одинаковы для чисел со знаком и без знака
Ключевое наблюдение состоит в том, что CMP в основном вычитание и:
В дополнении до двух (целочисленное представление, используемое в x86), сложение со знаком и без знака является одной и той же операцией
Это позволяет, например, разработчикам оборудования реализовать его более эффективно с помощью всего одной схемы.
Так, например, когда вы передаете входные байты инструкции ADD x86, все равно, подписаны они или нет.
Однако ADD устанавливает несколько флагов в зависимости от того, что произошлово время операции:
перенос: результат сложения без знака или вычитания не соответствует размеру бита, например: 0xFF + 0x01 или 0x00 - 0x01
Для сложениянеобходимо перенести 1 на следующий уровень.
знак: для результата установлен старший бит.Т.е.: отрицательный, если интерпретируется как подписанный.
переполнение: входные верхние биты равны 0 и 0 или 1 и 1, а инвертированный выходной сигнал противоположен.
Т.е. подписаноперация изменила подпись невозможным способом (например, положительный + положительный или отрицательный
Затем мы можем интерпретировать эти флаги таким образом, чтобы сравнение соответствовало нашим ожиданиям для чисел со знаком или без знака.
Эта интерпретация - именно то, что JA против JG и JB против JL делают для нас!
Пример кода
Вот фрагмент кода GNU GAS, чтобы сделать это болееconcrete:
/* 0x0 ==
*
* * 0 in 2's complement signed
* * 0 in 2's complement unsigned
*/
mov $0, %al
/* 0xFF ==
*
* * -1 in 2's complement signed
* * 255 in 2's complement unsigned
*/
mov $0xFF, %bl
/* Do the operation "Is al < bl?" */
cmp %bl, %al
Обратите внимание, что синтаксис AT & T "назад": mov src, dst
. Таким образом, вы должны мысленно изменить операнды для кодов условий, чтобы иметь смысл с cmp
. В синтаксисе Intel это будетбыть cmp al, bl
После этой точки будут сделаны следующие скачки:
- JB, потому что 0 <255 </li>
- JNA, потому что! (0> 255)
- JNL, потому что! (0 <-1) </li>
- JG, потому что 0>-1
Обратите внимание, как в данном конкретном примере имела значение подпись, например, JB, но не JL.
Пример выполнения с утверждениями .
Равные / отрицательные версии, такие как JLE / JNG, являются просто псевдонимами
Рассматривая Руководства разработчика ПО для архитектуры Intel 64 и IA-32, том 2 , раздел "Jcc- Перейти, если условие выполнено ", мы видим, что кодировки идентичны, например:
Opcode Instruction Description
7E cb JLE rel8 Jump short if less or equal (ZF=1 or SF ≠ OF).
7E cb JNG rel8 Jump short if not greater (ZF=1 or SF ≠ OF).