Иструкция STR. Сохранение данных

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

Инструкция STR (store) сохраняет данные по определенному адресу. Она имеет следующую форму:

STR{type} Xn, [Xs]

Инструкция STR сохраняет данные из первого регистра (Xn) по адресу, указанному во втором регистре (Xs). Синтаксис [Xs] указывает, что используется непрямая адресация памяти. То есть мы не просто кладем в регистр Xs значение из регистра Xn. Мы кладем значение из Xn по адресу, который хранится в Xs.

В качестве необязательного параметра type выступают теже типы данных, что и для инструкции LDR:

  • B: сохранение беззнакового байта

  • SB: сохранение байта со знаком

  • H: сохранение беззнакового полслова (16 бит)

  • SH: сохранение полслова со знаком (16 бит)

Загрузим данные в определенный участок памяти:

.global _start 
_start:
    mov x1, 6          // помещаем в регистр X1 число 6
    ldr x2, =num     // загружаем адрес переменной num

    str x1, [x2]       // сохраняем данные из X1 (число 6) по адресу из регистра X2 

    ldr x0, [X2]        // загружаем в регистр X0 данные из регистра X2

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

.data
    num: .quad 12

Здесь загружаем в регистр X2 адрес переменной num, которая имеет значени 12. Затем сохраняем данные из регистра X1 в участок памяти, адрес которого хранится в регистре X2 (фактически сохраняем в число num):

str x1, [x2]

Таким образом, в num окажется число 6.

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

.global _start 
_start:
    ldr x1, =num1      // загружаем в X1 адрес num1
    ldr x2, =num2       // загружаем в X2 адрес num2 

    ldr x3, [x1]        // загружаем данные из X1 в X3 (X3 = num1)
 
    STR X3, [x2]       // сохраняем данные из X3 по адресу из регистра X2 (num2 = num1)
 
    ldr x0, [x2]     // загружаем в регистр X0 данные из регистра X2

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

.data
    num1: .quad 22
    num2: .quad 33

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

  1. В регистр X1 загружается адрес числа num1

  2. В регистр X2 загружается адрес числа num2

  3. В регистр X3 загружаются данные из памяти по адреу из X1 (то есть по сути число num1)

  4. В память по адресу из X2 сохраняем данные из X3 (то есть теперь num2 = num1

Специальные формы инструкции STR

По умолчанию инструкция STR сохраняет данные такого размера, которые соответствуют размеру регистра из первого операнда. Если сохраняем данные их регистра X0-X30, то по адресу сохраняется 8 байт. Если первый операнд - 32-разрядный регистр W0-W30, то сохраняем 4 байта. Но это может быть не очень удобно. Например:

.global _start 
_start:
    ldr x1, =num1      // загружаем в X1 адрес num1
    mov x2, 21         // число для сохранения в num1
    str x2, [x1]        // сохраняем х2 по адресу в х1

    // проверяем значение num2
    ldr x2, =num2       // загружаем в X2 адрес num2 
    ldr x0, [x2]     // загружаем в регистр X0 данные из регистра X2; X0 = 0

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

.data
    num1: .byte 11
    num2: .byte 12
    num3: .byte 13
    num4: .byte 14

Здесь в секции данных определены четыре однобайтовых числа n1, n2, n3, n4. Допустим, в программе мы хотим изменить значение n1 и сохранить в нем число 21. Для этого загружаем адрес переменной в X1

ldr x1, =num1      // загружаем в X1 адрес num1

И число из регистра X2 сохраняем по адресу переменной num1

mov x2, 21         // число для сохранения в num1
str x2, [x1]        // сохраняем х2 по адресу в х1

Однако поскольку мы сохраняем значение из 64-битного регистра X2, то по адресу [X1] будут записаны 64 бита, то есть 8 байт. Соответственно будет изменена не только переменная n1, но и последующие переменные n2, n3, n4, так как они входя в диапазон 8 байт - в данном случае они получат значение 0. Это не лучший сценарий, так как мы бы хотели изменить только переменную n1, а остальные оставить неизменными. Для этого применяются специальные формы инструкции STR:

  • STRB: сохранение беззнакового байта

  • STRSB: сохранение байта со знаком

  • STRH: сохранение беззнакового полслова (16 бит)

  • STRSH: сохранение полслова со знаком (16 бит)

Данные инструкции в качестве первого параметра - сохраняемых данных принимают 32-разрядный регистр W0-W30.

Например, применим инструкцию STRB для сохранения одного байта:

.global _start 
_start:
    ldr x1, =num1      // загружаем в X1 адрес num1
    mov x2, 21         // число для сохранения в num1
    strb w2, [x1]      // сохраняем ТОЛЬКО 1 байт из х2 по адресу в х1

    // проверяем значение num2
    ldr x2, =num2       // загружаем в X2 адрес num2 
    ldr x0, [x2]     // X0 = 12

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

.data
    num1: .byte 11
    num2: .byte 12
    num3: .byte 13
    num4: .byte 14

Теперь мы сохраняем только один байт из W2 (X2) по адресу, который хранится в X1.

strb w2, [x1]

Поэтому теперь остальные переменные - n2, n3, n4 останутся нетронутыми.

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