Ряд инструкций позволяют установить однобайтовый операнд в 0 или 1 в зависимости от значений в регистре FLAGS. Основные из них:
setc
: устанавливает биты, если флаг переноса CF=1
setnc
: устанавливает биты, если флаг переноса CF=0
setz
: устанавливает биты, если флаг нуля ZF=1
setnz
: устанавливает биты, если флаг нуля ZF=0
sets
: устанавливает биты, если флаг знака SF=1
setns
: устанавливает биты, если флаг знака SF=0
seto
: устанавливает биты, если флаг переполнения OF=1
setno
: устанавливает биты, если флаг переполнения OF=0
Эти инструкции просто проверяют флаги без каких-либо дополнительных действий. Можно, например, использовать данные инструкции для проверки флага переноса после сдвига, поворота или арифметической операции.
Еще две дополнительные группы инструкций могут применяться после инструкции cmp. Они позволяют узнать, является ли один операнд меньше, равен или больше другого. Одна группа предназначена для беззнакового сравнения, а вторая группа - для сравнения результатов со знаком.
Для сравнения беззнаковых чисел:
Инструкция | Условие | Описание |
seta | CF = 0, ZF = 0 | Если первый операнд больше второго |
setnbe | CF = 0, ZF = 0 | Если первый операнд не меньше и не равен второму (по сути больше второго - аналог |
setae | CF = 0 | Если первый операнд больше или равен второму |
setnb | CF = 0 | Если первый операнд не меньше второго (аналог |
setb | CF = 1 | Если первый операнд меньше второго |
setnae | CF = 1 | Если первый операнд не больше и не равен второму (меньше второго - аналог |
setbe | CF = 1 или ZF = 1 | Если первый операнд меньше или равен второму |
setna | CF = 1 или ZF = 1 | Если первый операнд не больше второго (аналогичен |
sete | ZF = 1 | Если операнды равны (аналогичен |
setne | ZF = 0 | Если операнды не равны (аналогичен |
Для сравнения чисел со знаком:
Инструкция | Условие | Описание |
setg | SF = OF и ZF = 0 | Если первый операнд больше второго |
setnle | SF = OF и ZF = 0 | Если первый операнд не меньше и не равен второму (по сути больше второго - аналог |
setge | SF = OF | Если первый операнд больше или равен второму |
setnl | SF = OF | Если первый операнд не меньше второго (аналог |
setl | Флаги SF и OF не равны | Если первый операнд меньше второго |
setnge | Флаги SF и OF не равны | Если первый операнд не больше и не равен второму (меньше второго - аналог |
setle | Флаги SF и OF не равны или ZF = 1 | Если первый операнд меньше или равен второму |
setng | Флаги SF и OF не равны или ZF = 1 | Если первый операнд не больше второго (аналогичен |
sete | ZF = 1 | Если операнды равны (аналогичен |
setne | ZF = 0 | Если операнды не равны (аналогичен |
Общий формат инструкций:
setxxxx операнд8
В качестве параметра передается 8-разрядный операнд, который может представлять регистр или переменную.
В ряде языков программирования высокого уровня есть логический тип данных (bool, boolean), который может содержать одно из двух значений - true
или
false
, то есть истинно или ложь. С помощью подобного типа данных можно установить, что какое-то условие верно, истинно или не верно, ложно.
И подобные иИнструкции setxxx
позволяют преобразовывать результат сравнения в подобное логическое значение. Если условие верно, то устанавливаетя 1, если неверно - то 0.
Например:
.code main proc mov eax, 0 mov ecx, 6 mov edx, 6 cmp ecx, edx sete al ret main endp end
Здесь сравниваем значения регистров ECX и EDX. Инструкция
sete al
Проверяет равенство операндов из инструкции CMP, а по сути проверяет флаг нуля ZF - если он равен 1, то в регистр AL помещается значение 1. Если флаг нуля равен 0, то в регистр AL помещается 0. В данном случае операнды равны, поэтому в AL будет 1.
В языках высокого уровня это было бы аналогично следующему выражению
bool al = ecx == edx:
Подобным образом можно устанавливать переменные. Переменная в этом случае должна представлять тип byte
.data bool byte ? .code main proc mov ecx, 6 mov edx, 6 cmp ecx, edx setne bool movzx eax, bool ret main endp end
Здесь проверяем на неравенство, поэтому переменная bool будет равна 1, если значение регистров ECX и EDX не равны.
Подобным образом можно сравнивать более сложные конструкции. Например, возьмем следующий код на си-подобном языке:
bool result = ((a <= b) && (d == e)):
Здесь одновременно должно быть a меньше или равно b и d равно e. В этом случае выражение будет истинным. Определим подобное сравнение на ассемблере:
.data bool byte ? .code main proc mov ecx, 6 mov edx, 16 cmp ecx, edx setle bl ; ecx <= edx mov r8d, 5 mov r9d, 5 cmp r8d, r9d sete bh ; r8d == r9d and bh, bl ; ecx <= edx && r8d == r9d movzx eax, bh ret main endp end