Инструкции условного выбора

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

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

  • CSEL: инструкция условного выбора. Имеет следующий синтаксис:

    CSEL Xd, Xn, Xm, cond

    Аналогична псевдокоду

    if (cond == true)
        Xd = Xn
    else
        Xd = Xm
    
  • CSINC: инструкция условного инкремента. Имеет следующий синтаксис:

    CSINC Xd, Xn, Xm, cond

    Аналогична псевдокоду

    if (cond == true)
        Xd = Xn
    else
        Xd = Xm + 1
    
  • CSINV: инструкция условной инверсии. Имеет следующий синтаксис:

    CSINV Xd, Xn, Xm, cond

    Аналогична псевдокоду

    if (cond == true)
        Xd = Xn
    else
        Xd = NOT(Xm)
    
  • CSNEG: инструкция условного отрицания. Имеет следующий синтаксис:

    CSNEG Xd, Xn, Xm, cond

    Аналогична псевдокоду

    if (cond == true)
        Xd = Xn
    else
        Xd = 0 - Xm
    
  • CSET: инструкция условной установки регистра. Имеет следующий синтаксис:

    CSET Xd, cond

    Аналогична псевдокоду

    if (cond == true)
        Xd = 1
    else
        Xd = 0
    
  • CSETM: инструкция условной установки маски. Имеет следующий синтаксис:

    CSETM Xd, cond

    Аналогична псевдокоду

    if (cond == true)
        Xd = -1    // все разряды Xd устанавливаются в 1
    else
        Xd = 0
    
  • CINC: инструкция условного инкремента. Имеет следующий синтаксис:

    CINC Xd, Xn, Xm, cond

    Аналогична псевдокоду

    if (cond == true)
        Xd = Xn + 1
    else
        Xd = Xn
    
  • CINV: инструкция условной инверсии. Имеет следующий синтаксис:

    CINV Xd, Xn, cond

    Аналогична псевдокоду

    if (cond == true)
        Xd = NOT(Xn)
    else
        Xd = Xn
    
  • CNEG: инструкция условного отрицания. Имеет следующий синтаксис:

    CNEG Xd, Xn, cond

    Аналогична псевдокоду

    if (cond == true)
        Xd = 0 - Xn
    else
        Xd = Xn
    

Эти инструкции во многом похожи. В качестве последнего операнда они принимают одно из условий, перечисленых в https://metanit.com/assembler/arm64/2.7.php.

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

.global _start

_start:
    mov x1, #19         
    mov x2, #100 
    cmp x1, x2             // сравниваем x1 и x2
    csel x0, x1, x2, LS    // если верно условие LS, Х0=Х1, если нет - Х0=Х2

    mov x8, #93         // номер функции Linux для выхода из программы - 93
    svc 0               // вызываем функцию и выходим из программы

Здесь инструкция CMP сравнивает числа из регистров X1 и Х2, то есть по сути выполняем вычитание 19 - 100 и по итогам операции устанавливаем флаги. Далее инструкция

CSEL X0, X1, X2, LS

Проверяет условие LS. Это условие представляет условие "меньше или равно" или <=, при котором C-флаг сброшен, а Z-флаг установлен. Если это условие верно, то есть Х1 меньше или равно Х2, то в Х0 помещаем число из Х1. Если условие не верно, то в Х0 помещаем данные из Х2.

В данном случае число из Х1 меньше чем число из Х2, соответственно условие LS будет верно. Поэтому инструкция CSEL X0, X1, X2, LS присваивает регистру X0 значение регистра X1, то есть число 19.

Другой пример:

.global _start

_start:
    mov x1, #99         
    mov x2, #100 
    mov x3, #1         
    mov x4, #2 
    cmp x1, x2             // сравниваем x1 и x2
    csel x0, x3, x4, EQ    // если X1==X2, то Х0=Х3, если X1!=X2, то Х0=Х4

    mov x8, #93         // номер функции Linux для выхода из программы - 93
    svc 0               // вызываем функцию и выходим из программы

Здесь инструкция CSEL помещает в X0 значение из X3, если верно условие EQ. Иходя из предыдущей инструкции CMP, условие EQ будет верно, если X1 == X2. В данном случае это условие не выполняется, поскольку в X1 и X2 разные значения. Поэтому условие EQ не верно, и в регистр X0 помещается число из X4 (число 2).

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