Строки

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

Строки представляют набор символовю Если нам надо определить строку, то мы можем указать набор символов в одинарных или двойных кавычках:

.data
    text byte "Hello"
.code
main proc
    mov al, text   ; в регистре AL числовой код символа H - 72
    ret
main endp
end

Здесь переменная text представляет набор из пяти байтов. Если мы поместим переменную, которая представляет набор байт, в регистр, то он будет содержать код первого байта.

Также можно через запятую перечислять числовые коды символов, которые входят в строку:

.data
    text byte 72, 101, 108, 108, 111
.code
main proc
    xor rax, rax
    mov al, text   ; в регистре AL числовой код символа H
    ret
main endp
end

Строки с нулевым байтом

Распространенным типом строк являются строки, которые оканчиваются на нулевой байт. Что может быть очень удобно при операциях со строками, поскольку мы знаем где у нее завершение. И, например, при взаимодействии с кодом C/C++ обычно требуется, чтобы строки завершались нулевым байтом - признаком завершения строки. В этом случае при определении строк в ассемблере можно в конце строки дописать числовой код символа:

.data
    text byte "Hello", 0

Здесь к строке Hello добавляется нулевой байт.

Используем нулевой байт для подсчета количества символов в строке:

.data
    text byte "Hello", 0
.code
main proc
    lea rbx, text
    xor rax, rax    ; в регистре RAX по умолчанию 0
startWhile: 
    cmp byte ptr [rbx+rax*1], 0     ; сравниваем значение по адресу [rbx+rax*1] c 0 
    je endWhile                 ; если дошли до нулевого байта, выходим из цикла
    inc rax                     ; увеличиваем счетчик на 1
    jmp startWhile              ; переходим обратно к startWhile
endWhile: 
    ret
main endp
end

В данном случае регистр RAX выступает в качестве счетчика - он хранит количество символов и по умолчанию равен 0.

В регистр RBX загружаем адрес строки text. На метку startWhile проецируем начило цикла, в котором будем подсчитывать количество символов. Для подсчета с помощью инструкции cmp сравниваем значение по адресу [rbx+rax*1] с нулевым байтом.

cmp byte ptr [rbx+rax*1], 0

В начале программы, поскольку RAX равен 0, то выражение [rbx+rax*1] даст нам адрес первого символа в строке text. Если символ равен нулевому байту, то переходим к метке endWhile, то есть фактически выходим из цикла

je endWhile

Если же символ по адресу [rbx+rax*1] не нулевой байт, то увеличиваем значение в регистре RAX на 1 и переходим опять к метке startWhile. И таким образом, сравниваем следующий символ строки text с нулевым байтом.

С одной строны, это удобно, мы всегда знаем, где у строки конец, и можем определить строку из произвольного количества символов. В то же время в каких=то ситуациях это может быть не оптимальный способ представления строки. Например, опять же, чтобы узнать количество символов, нам надо перебрать всю строку.

Строки с фиксированным количеством символов

В строках с фиксированным количеством символов обычно первый символ указывает на количество символов:

.data
    text byte 5, "Hello"
.code
main proc
    lea rbx, text
    movzx rax, byte ptr [rbx]    ; в регистре RAX - 5
    ret
main endp
end

Однако в этом случае мы ограничены строками длиной 255 байт (из которых первый байт - длина строки). Также можно автоматически вычислять длину с помощью констант:

.data
    text byte textLength, "Hello World"
    textLength = $-text-1
.code
main proc
    lea rbx, text
    mov rax, textLength     ; в регистре RAX - 11
    ret
main endp
end
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850