STRB и манипуляции с символами в строке

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

Инструкция STRB (store byte) является частным случаем инструкции STR, она сохраняет наименьший байт из первого регистра (Wn) по адресу, указанному во втором регистре (Xs).

STRB Wn, [Xs]

Поскольку строки представляют собой наборы символов, которые в общем случае в общем случае равны 1 байту, то эту инструкцию удобно применять для манипуляции символами в строке. Рассмотрим небольшой пример:

.global _start

_start: LDR X1, =message
    MOV W0, #'a'
    STRB W0, [X1]       // помещаем по адресу [X1] символ 'a'

    // вывод строки на консоль
    MOV X0, #1          // 1 = StdOut - стандартный поток вывода
    MOV X2, #6         // длина строки
    MOV X8, #64         // функция Linux для вывода в поток
    SVC 0               // вызываем функцию Linux
    // выход из программы
    MOV X0, 0
    MOV X8, #93         // функция Linux для выхода из программы
    SVC 0               // вызываем функцию Linux
.data
message: .ascii "hello\n"

Здесь в регистр X1 для вывода строки на консоль загружается адрес сообщения message. Используя выражение [X1], мы можем обратиться к адресу первого символа этой строки. Поэтому код

MOV W0, #'a'
STRB W0, [X1]       // помещаем по адресу [X1] символ 'a'

сначала загружает в регистр W0 числовой код символа 'a', а затем загружает этот код по адресу, который хранится в регистре X1. В итоге при выводе строки на консоль мы увидим

aello

Фактически мы меняет первый символ строки. Но что, если мы хотим поменять не первый, а любой другой символ строки, например, второй? Для этого определим следуюшую программу:

.global _start

_start: LDR X1, =message
    MOV W0, #'a'
    ADD X1, X1, #1      // добавляем к адресу 1 - переход к адресу второго символа
    STRB W0, [X1]      // помещаем по адресу [X1] символ 'a'

    // вывод строки на консоль
    MOV X0, #1          // 1 = StdOut - стандартный поток вывода
    LDR X1, =message    // переустанавливаем адрес на начало строки
    MOV X2, #6         // длина строки
    MOV X8, #64         // функция Linux для вывода в поток
    SVC 0               // вызываем функцию Linux
    // выход из программы
    MOV X0, 0
    MOV X8, #93         // функция Linux для выхода из программы
    SVC 0               // вызываем функцию Linux
.data
message: .ascii "hello\n"

Ключевым моментом здесь является добавление к X1 (который хранит адрес строки) числа 1, то есть мы сдвигаемся относительно адреса начала строки на 1 байт вперед (адрес второго символа - "e"):

MOV W0, #'a'
ADD X1, X1, #1      // добавляем к адресу 1 - переход к адресу второго символа
STRB W0, [X1]      // помещаем по адресу [X1] символ 'a'

Соответственно теперь консоль выведет

hallo

Замена всех символов

Теперь усложним задачу - заменим все символы строки с использованием циклических конструкций:

.global _start

_start: LDR X1, =message
    MOV W5, #5          // счетчик - заменить 5 символов
    MOV W0, #'a'
    ADD X1, X1, #4      // добавляем к адресу 4 - переход к адресу последнего символа
loop:
    STRB W0, [X1]      // помещаем по адресу [X1] символ 'a'
    SUB X1, X1, #1     // уменьшаем адрес на 1 - перех к адресу предыдущего символа
    SUBS W5, W5, #1    // уменьшаем значение счетчика на 1 с установкой флагов
    B.NE loop          // если счетчик не равен 0, переходим обратно к метке loop
endloop:
    // вывод строки на консоль
    MOV X0, #1          // 1 = StdOut - стандартный поток вывода
    LDR X1, =message
    MOV X2, #6         // длина строки
    MOV X8, #64         // функция Linux для вывода в поток
    SVC 0               // вызываем функцию Linux
    // выход из программы
    MOV X0, 0
    MOV X8, #93         // функция Linux для выхода из программы
    SVC 0               // вызываем функцию Linux
.data
message: .ascii "hello\n"

Здесь заменяем все символы строки "hello" на символ "a". Для этого сначала определяем счетчик:

MOV W5, #5          // счетчик - заменить 5 символов

В данном случае заменяем с конца строкию. Поэтому переходим к адресу предпоследнего символа (так как последний символ - перевод строки \n менять не надо):

ADD X1, X1, #4

В цикле заменяем символ, уменьшаем значение счетчика и помещаем в X1 новый адрес - адрес предыдущего символа:

STRB W0, [X1]      // помещаем по адресу [X1] символ 'a'
SUB X1, X1, #1     // уменьшаем адрес на 1 - перех к адресу предыдущего символа
SUBS W5, W5, #1    // уменьшаем значение счетчика на 1 с установкой флагов
B.NE loop          // если счетчик не равен 0, переходим обратно к метке loop

Если значение W0 не равно 0, то переходим обратно к метке loop

То есть таким образом мы заменим все пять символов на символ "a":

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