Поиск в строке

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

Для поиска определенного элемента в строке применяется следующий набор инструкций:

  • scasb: поиск в строке байтов

  • scasw: поиск в строке слов

  • scasd: поиск в строке двойных слов

  • scasq: поиск в строке четверных слов

Данные инструкции принимают только один операнд - строку, в которую помещается результат поиска и адрес которой загружается в регистр RDI. Строка для поиска загружается в регистре AL (scasb), AX (scasw), EAX (scasd) или RAX (scasq). Инструкции scas сравнивают значение в аккумуляторе (AL, AX, EAX или RAX) со значением, на которое указывает RDI, а затем увеличивает (или уменьшает) значение RDI на 1, 2, 4 или 8. В соответствии с результатом сравнения процессор устанавливает флаги. Так, если символ найден, то устанавливается флаг нуля, а регистр RDI указывает на символ, следующий за найденным.

При применении префикса repe инструкции scas просматривают строку в поисках элемента, не соответствующего значению в аккумуляторе. При использовании префикса repne scas сканирует строку в поисках первого элемента, равного значению в аккумуляторе. Регистр RCX в этом случае хранит количество элементов, а не байтов, которые необходимо обработать при сканировании.

Например, найдем индекс символа в строке:

.data
text byte "Hello", 0
len = $ - text         ; длина первой строки 
char byte 'l'               ; символ для поиска
.code
main proc
    lea rdi, text   ; загружаем адрес переменной text
    mov rsi, rdi    ; копируем адрес в RSI для последующего поиска индекса
    mov al, char    ; в AL символ для поиска
    mov rcx, len    ; в RCX количество символов строки
    repne scasb     ; ищем байт
    jz found        ; если символ найден, устанавливается флаг нуля ZF
    mov rax, -1     ; если символ не найден, в RAX число -1
    jmp exit
found:              
    sub rdi, rsi    ; если символ найден, получаем индекс следующего символа после найденного
    dec rdi         ; отнимает 1 байт - получем индекс найденного символа
    mov rax, rdi    ; в RAX индекс 
exit:
    ret
main endp
end

Здесь в строке "Hello" ищем символ "l". Для этого строку для поиска загружаем в RDI, а в AL - символ (байт), который будем искать.

Если при выполнении инструкции scas элемент был найден, то устанавливается флаг нуля. И мы можем это проверить и выполнить определенные действия. В данном случае, если символ найден, от значения в RDI (адрес следующего символа за найденным) отнимаем начальный адрес строки text (адрес первого символа строки text), который для удобства сохранили в регистр RSI и таким образом получаем расстояние в байтах между первым символом и следующим за найденным символом. Поскольку все элементы строки - байты, то это расстояние будет представлять индекс следующего символа за найденным. Соответственно, чтобы получить индекс найденного символа (а не следующего за ним), надо от этого расстояния отнять 1 (размер одного элемента в байтах). Например, при поиске символа "l" в строке "Hello" мы получим 2 - это индекс третьего символа.

Если символ не найден, то в регистр RAX помещаем -1.

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