Инструкции условного копирования

Последнее обновление: 20.09.2023

Нередко сравнение двух значений произодится, чтобы в зависимости от результатов сравнения загрузить в регистр некоторое значение или, наоборот, не загружать это значение, если проверка или сравнение не пройдены. Для упрощения подобных действий процессоры x86-64 поддерживают набор инструкций условного копирования. Инструкции перемещения с проверкой флагов:

  • cmovc / cmovb / cmovnae: перемещает, если флаг переноса CF = 1

  • cmovnc / cmovnb / cmovae: перемещает, если флаг переноса CF = 0

  • cmovz / cmove: перемещает, если флаг нуля ZF = 1

  • cmovnz / cmovne: перемещает, если флаг нуля ZF = 0

  • cmovs: перемещает, если флаг знака SF = 1

  • cmovns: перемещает, если флаг знака SF = 0

  • cmovo: перемещает, если флаг переполнения OF = 1

  • cmovno: перемещает, если флаг переполнения OF = 0

Отдельная группа инструкций предназначена для сравнения с копированием. Здесь есть инструкции для сравнения беззнаковых чисел:

  • cmova: перемещает, если первый операнд больше второго (CF=0, ZF=0)

  • cmovnbe: перемещает, если первый операнд не меньше и не равен второму (CF=0, ZF=0)

  • cmovae / cmovnc / cmovnb: перемещает, если первый операнд больше или равен второму (CF=0)

  • cmovnae / cmovc / cmovb: перемещает, если первый операнд меньше второго (CF=1)

  • cmovbe: перемещает, если первый операнд меньше или равен второму (CF=1 или ZF=1)

  • cmovna: перемещает, если первый операнд не больше второго (CF=1 или ZF=1)

И инструкции для сравнения чисел со знаком:

  • cmovg: перемещает, если первый операнд больше второго (SF=OF или ZF=0)

  • cmovnle: перемещает, если первый операнд больше второго (SF=OF или ZF=0)

  • cmovge: перемещает, если первый операнд больше или равен второму (SF=OF)

  • cmovnl: перемещает, если первый операнд больше или равен второму (SF=OF)

  • cmovl: перемещает, если первый операнд меньше второго (SF != OF)

  • cmovnge: перемещает, если первый операнд меньше второго (SF != OF)

  • cmovle: перемещает, если первый операнд меньше или равен второму (SF != OF или ZF=1)

  • cmovng: перемещает, если первый операнд меньше или равен второму (SF != OF или ZF=1)

И две общие инструкции как для чисел со знаком, так и для беззнаковых чисел:

  • cmove: перемещает, если первый операнд равен второму (ZF=1). Аналогичен инструкции cmovz

  • cmovne: перемещает, если первый операнд не равен второму (ZF=0). Аналогичен инструкции cmovnz

Первый параметр этих инструкций представляет регистр общего назначения (16, 32 или 64-битный). Второй параметр - либо регистр, либо переменная (также 16, 32 или 64-битные)

Например, возьмем следующую программу:

.data
    n1 dword 0FFFFFFFFh
    n2 dword  1h

    res0 dword 0
    res1 dword 1
.code
main proc
    mov eax, n1
    add eax, n2
    jc carry_set
    mov eax, res0 
    ret
carry_set:
    mov eax, res1 
    ret
main endp
end

Здесь складываем 2 числа. И если при сложении устанавливается флаг переноса, то осуществляется переход к метке carry_set, где в регистр EAX помещается 1. С помощью инструкций условного перемещения эту программу можно сократить так:

.data
    n1 dword 0FFFFFFFFh
    n2 dword  1h

    res0 dword 0
    res1 dword 1
.code
main proc
    mov eax, n1
    add eax, n2
    cmovnc eax, res0   ; Если CF = 0
    cmovc eax, res1    ; Если CF = 1
    ret
main endp
end

Другой пример - поместим в регистр EAX определенное значение в зависимости от результата сравнения:

.data
    n1 dword 22
    n2 dword 22

    res0 dword 0
    res1 dword 1
.code
main proc
    mov eax, n1
    cmp eax, n2
    cmovne eax, res0   ; Если ZF = 0
    cmove eax, res1    ; Если ZF = 1
    ret
main endp
end

В данном случае если числа n1 и n2 равны, в регистр EAX помещается число 1, иначе помещается число 0.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850