Почему CMP (сравнивать) иногда устанавливает флаг переноса в сборке 8086? - PullRequest
8 голосов
/ 07 ноября 2011

Я читал и с набором инструкций 8086, он говорит, что CMP (сравнить) может установить флаг переноса. Я понимаю, что сравнение вычитает два операнда, но мне было интересно, если кто-нибудь может привести пример, когда это так.

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

Кроме того, я понимаю, что если 3 - 5 = -2 установит отрицательный флаг ... когда будет установлен перенос?

Ответы [ 4 ]

6 голосов
/ 07 ноября 2011
  • Флаг переноса устанавливается после операции, которая привела к недостаточному или переполнению.Например, вычитание 10 из 6 приведет к недостаточному переполнению и установит флаг переноса.Аналогично, добавление 1 к максимальному значению регистра приведет к переполнению и установит флаг переноса.
  • Флаг переноса также изменяется во время операции сдвига, он устанавливается на значение последнего сдвинутого битавне регистра назначения.
  • Битовое тестирование помещает значение проверенного бита в флаг переноса.Операционные коды, которые делают это: BT, BTC, BTR и BTS.
  • Инструкции, которые непосредственно влияют на флаг переноса: CLC, CMC и STC.
  • Во время сравнения устанавливается флаг переносаточно так же, как если бы два операнда были вычтены.
  • Во время отрицания (NEG) флаг переноса устанавливается, если только операнд не равен нулю, в этом случае он очищается.
2 голосов
/ 09 ноября 2011

Флаг переноса обычно устанавливается при использовании арифметики без знака.Например, добавление двух чисел без знака (результат которых не помещается в регистр) не будет поднимать флаг переполнения, а только будет переносить флаг.Однако при использовании знаковой арифметики в таком событии устанавливается флаг переполнения.

1 голос
/ 09 ноября 2011

Вы можете найти примеры, когда флаги переноса и переполнения установлены на 0 и 1 после сложения или вычитания целых чисел в этот ответ на связанный вопрос.
Вы также можете найти там образецКод на C, эмулирующий сложение с переносом и вычитание с инструкциями заимствования для 8-битных чисел, и вы можете поиграть с этим, может быть, получите больше примеров.

Формат вывода там примерно такой:
127( 127) - 255( -1) - 1 = 127( 127) CY=1 OV=0
Где каждое число представлено как без знака, так и со знаком в скобках (дополнение 2) рядом с ним.Число перед = является флагом переноса перед ADC / SBB.CY= и OV= показывают флаги переноса и переполнения после ADC / SBB.

Сравнение делает почти то же самое, что вычитание без заимствования, за исключением того, что оно влияет только на флаги переноса, переполнения, знака и нуляи четность и вспомогательный перенос, но они здесь не важны) без изменения какого-либо числа в регистре / памяти.

0 голосов
/ 09 апреля 2018

https://www.hellboundhackers.org/articles/read-article.php?article_id=729

В качестве краткого изложения я написал эту статью для двух целей. Во-первых, это интересно, и всегда полезно больше знать о том, как работает ваш компьютер. Во-вторых, всегда есть программы, в которых с флагами манипулируют напрямую, и полезно знать, какое влияние они окажут на прыжки. Например, что-то простое, как CMP eax, ebx Где-то может запутать большинство начинающих реверсеров, но, надеюсь, не после этой статьи. Наслаждайтесь:)

[Важное примечание: я буду использовать 8-битные целые числа для моих примеров, когда я записываю двоичные числа. Просто помните, что, хотя 8-битные целые числа обычно не используются в программировании, те же самые правила, которые я обсуждаю, применяются к целым числам с большим количеством битов]

Инструкция CMP:

Команда CMP действует путем выполнения подразумеваемого вычитания двух операндов. Это означает, что результат не сохраняется в памяти. Вычитая их, он делает несколько быстрых тестов, обновляя флаги Z, O, C, S и P. Флаг P, или четность, используется редко, поэтому мы будем его игнорировать в целях краткости.

Двоичное вычитание выполняется путем добавления отрицательного варианта второго операнда из первого. Это так же, как то, что вы узнали в средней школе, о том, как 4 + 3 = 4 - (-3), и наоборот. В конце статьи я объясню, как это делается, но сейчас я перейду к более важным вопросам, поскольку эти знания на самом деле не нужны для взлома или кодирования.

Знак и нулевой флаг:

Четыре флага, которые может установить инструкция CMP - Z, O, C и S, известны как флаги нуля, переполнения, переноса и знака соответственно. Флаг нуля устанавливается всякий раз, когда результат вычитания равен нулю. Это, конечно, происходит только тогда, когда операнды равны. Флаг знака устанавливается, когда результат вычитания отрицательный. Хотя мы склонны думать, что это означает, что флаг знака в сочетании с флагом нуля достаточно для проверки всех>> = <и <=, это не так, поскольку результат может быть отрицательным, даже если первое число больше второй. Это из-за переполнения. </p>

Флаг переполнения:

Целые числа со знаком представляются в двоичном виде с тем же количеством битов, что и целые числа без знака. Это означает, конечно, что знак должен быть установлен в одном из битов целого числа. Знаковые целые числа хранят знак в MSB (самый значащий бит). Это означает, что, в то время как 00000001 преобразуется в 1 в десятичном виде, 10000001 преобразуется в -127. Я буду обсуждать, почему это -127, а не -1 или -2 позже в этой статье. Когда процессор выполняет вычитание, он оборачивается, если вычитание опускается ниже 00000000 или выше 11111111. Поэтому, если вы вычтите отрицательное число из положительного или вычтите положительное число из отрицательного, есть вероятность, что ответ будет переполнение через границу. Например, 100 - (-100) равно 200, но самое высокое значение 8-разрядного целого числа со знаком может быть 127, поэтому 200 будет проходить через верхнюю границу и получится как отрицательное число, даже если оно должно быть положительным , Та же проблема возникает с -100 - 100; Он проходит через нижний предел и в конечном итоге оказывается положительным, когда должен быть отрицательным, вызывая недостаточный поток. Обратите внимание, что нижнее значение также устанавливает флаг переполнения, и переполнение будет ссылаться как на переполнение, так и на понижение в дальнейшем в статье. CPU проверяет это и устанавливает флаг переполнения, если это происходит.

Нести флаг:

Флаг переноса устанавливается, когда, если оба операнда интерпретируются как целые числа без знака, первый из них больше. Это легко определить, потому что это происходит всякий раз, когда вычитание проходит через 00000000 в верхний диапазон (11111111). Например, 00000001 - 00000010 = 11111111, поэтому перенос установлен. Однако 00000010 - 00000001 = 00000001, поэтому перенос не установлен.

...