Инструкция 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