Сложение. Инструкция ADD

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

Инструкция ADD складывает второй и третий параметры и результат помещают в регистр из первого параметра. Она имеет следующие формы:

ADD Xd, Xn, Xm      // Xd = Xn + Xm
ADD Xd, Xn, #imm    // Xd = Xn + #imm
ADD Xd, Xn, #imm, shift     // сложение со сдвигом - непосредственный операнд #imm сдвигается с помощью выражения shift
ADD Xd, Xn, Xm, shift #N    // сложение со сдвигом - регистр Xm сдвигается с помощью выражения shift #N
ADD Xd, Xn, Xm, extend #N   // сложение с расширением - регистр Xm расширяется с помощью выражения extend #N

Добавим к значению из регистра X1 число 22 и поместим результат в регистр X2

.global _start
 
_start: 
    MOV X1, #12         // X1 = 12
    ADD X0, X1, #22     // X0 = X1 + 22 = 12 + 22 = 34
 
    MOV X8, #93         // номер функции Linux для выхода из программы - 93
    SVC 0               // вызываем функцию и выходим из программы

Здесь инструкция ADD складывает значение регистра X1 и непосредственный операнд - число 22 и помещает результат в регистр X0.

Вместо непосредственного операнда можно использовать значение из другого регистра:

MOV X1, #12         // X1 = 12
MOV X2, #10
ADD X0, X1, X2   // X0 = X1 + X2 = 12 + 10 = 22

Сложение со сдвигом

При сложении можно применять сдвиг и поворот. При этом если сдвиг применяется к непосредственному операнду, то значение сдвига (количество разрядов, на которые происходит сдвиг) должно быть равно 0 или 12:

ADD X2, X1, #0x10, LSL 12     // X2 = X1 + 0x10000

При сдвиге значения из регистра такого ограничения нет:

ADD X2, X1, X0, LSL 2     // X2 = X1 + (X0 * 4)

Операции расширения

Операции расширения позволяют извлечь один байт, полслова (2 байта) или слово (4 байта) из одного регистра

  • uxtb: извлекает один младший байт, который рассматривается как число без знака

  • uxth: извлекает беззнаковые полслова - два младших беззнаковых байта

  • uxtw: извлекает беззнаковое слово - четыре младших беззнаковых байта

  • sxtb: извлекает один младший байт, который рассматривается как число со знаком

  • sxth: извлекает младшие полслова (2 байта) со знаком

  • sxtw: извлекает младшее слово (4 байта) со знаком

Данные операторы не работают с командой mov, но работают с командой add:

ADD X2, X1, X0, SXTB    // X2 = X1 + байт со знаком из регистра X0

В данном случае из регистра Х0 извлекается байт со знаком, добавляется к значению из регистра Х1, и результат помещается в регистр Х2.

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

ADD X2, X1, X0, SXTB #2    // X2 = X1 + (1_знаковый_байт_из_Х0  << 2)

Подобным образом можно извлечь полслова или слово:

ADD X2, X1, X0, UXTH          // X2 = X1 + беззнаковые_полслова_из_регистра_X0
ADD X2, X1, X0, UXTW       // X2 = X1 + беззнаковое_слово_из_регистра_X0

Например:

.global _start
 
_start: 
    MOV X1, #0x12FD         // X1 = 4861
    MOV X2, #0x2            // X2 = 2
    ADD X0, X2, X1, UXTB   // X0 = X2 + младший байт из X1 = 0x2 + 0xFD = 0xFF
 
    MOV X8, #93         // номер функции Linux для выхода из программы - 93
    SVC 0               // вызываем функцию и выходим из программы

Здесь извлекается младший байт из регистра X1 и складывается со значением из регистра X2. То есть младший байт числа 0x12FD равен FD. Прибавляем их к 0x2 и получается 0xFF или 255 в десятичной системе.

Пример с расширением и сдвигом влево:

.global _start
 
_start: 
    MOV X1, #0x12FD         // X1 = 4861
    MOV X2, #0x2
    ADD X0, X2, X1, UXTB #4   
    // X0 = X2 + младший байт из X1, сдвинутый влево на 4 бита = 0x2 + (0xFD << 4) =0x2 + 0xD0 = 0xD2
 
    MOV X8, #93         // номер функции Linux для выхода из программы - 93
    SVC 0               // вызываем функцию и выходим из программы

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