Чтобы внести ясность: я уверен, что приведенный ниже вывод неверен, но надеюсь, что кто-нибудь укажет, где в моем «доказательстве» я ошибаюсь.
Я пытаюсь доказать, что инструкция x86 setb
действительно реализует x<y как беззнаковое сравнение при использовании после инструкции cmp
. В частности, давайте рассмотрим (синтаксис ATT, а суффиксы, указывающие количество бит, я пренебрегу)
# Compare two registers, e.g., %eax and %ebx with values y and x, respectively, when unsigned
cmp %ebx, %eax
# Set %al to 1 if %eax is below %ebx (unsigned comparison)
setb %al
Утверждается, что %al получает значение 1 в конце этого выражения тогда и только тогда, когда значения x,y подчиняются x<y, если считать их беззнаковыми. Обратите внимание, что в синтаксисе ATT инструкция cmp
вычитает содержимое %ebx из содержимого %eax и что эта операция соответствующим образом устанавливает соответствующие флаги условий, включая флаг выполнения, который здесь представляет интерес. То есть битовый шаблон помещается в модуль вычитания для вычисления x(-^u)y, где я использую это обозначение для описания вычитания без знака, а - для описания вычитания соответствующих целых чисел.
Теперь вот моя проблема. Предположим, x<y. Мы хотим показать, что выполнение является результатом вычитания. Предположим, что каждое число состоит из w бит. Я знаю (из моего сообщения, CS:APP3e Брайанта и О'Халларона), что
x(-^u)y := x(+^u)((-^u) y) = x(+^u)(2^w - y) = 2^w + x - y < 2^w,
поэтому якобы никакого выполнения получено не было, поскольку результат укладывается в наши w биты. То есть никакого выполнения. Это только одно направление «доказательства», но я уже ясно вижу, что не прав. Хотя где я ошибаюсь?
Понял. Итак, вы говорите, что когда выполняется вычитание (предположительно с использованием аппаратного сумматора при дополнении вычитаемого и добавлении 1 для получения дополнения до 2, как это стандартно в компьютерных архивных книгах), блок сумматора/вычитателя фактически дополняет выходной перенос в случае вычитания. , и этот дополненный перенос — это то, что мы видим как флаг CF? @PeterCordes
Да, для x86 и некоторых других ISA, в отличие от ARM и некоторых других.
Супер, как всегда спасибо за помощь! Буду рад принять ответ на этот счет, если хотите. @PeterCordes
Я не понимаю приоритет операторов =, := и < в вашем выражении выше. Не могли бы вы ввести скобки, чтобы было понятно?
Мои извинения, я намеревался попытаться использовать стандартные математические обозначения, но на этом сайте нет MathJax, поэтому моя попытка потерпела неудачу. Кстати, := «равно по определению», = равно, < меньше. То есть они используются в математическом смысле, а не в смысле языка программирования. @ЭрикЭйдт
sub
и cmp
в x86 устанавливают CF, если есть заимствование из вычитания. Это тот случай, когда нет переноса от сложения побитового обратного числа с переносом 1, как это делает двоичный сумматор-вычитатель в ALU.
Некоторые ISA (например, ARM) противоположны x86 для sub
, устанавливают свой флаг переноса непосредственно из выполнения сумматора-вычитателя. x86 (и некоторые другие ISA) инвертируют его.
Связано: Арифметические тождества и EFLAGS — обратите внимание, что правильный asm, эквивалентный sub
, — это одно сложение с переносом 1
и cmc
, а не отдельные neg
и add
, если вас волнует результат EFLAGS.
sub
иcmp
в x86 устанавливают CF, если есть заимствование из вычитания. Это тот случай, когда нет переноса от сложения обратного (с переносом 1). Некоторые другие ISA (например, ARM) противоположны x86 для sub, устанавливая свой флаг переноса непосредственно при выполнении двоичного сумматора-вычитателя. en.wikipedia.org/wiki/Adder%E2%80%93вычитатель . Также по теме: Арифметические тождества и EFLAGS