Замена подстроки в строке на Ассемблере
Во всех языках высокого уровня среди функций работы со строками присутствуют функции замены заданной подстроки в строке. В Ассемблере такой функции нет, как нет ее и среди функций стандартных библиотек. Замена подстроки на строку такой же длины обычно сложностей не составляет, так как ее можно выполнить прямо в исходной строке без выделения дополнительной памяти. Замена на строку произвольной длины, в том числе и пустую, будет посложнее. Для этого я написал следующую функцию.Code (Assembler) : Убрать нумерацию
- ;-----------------------------------------------------
- ; Функция замены подстроки в строке
- ;-----------------------------------------------------
- ; lpSrc - указатель на исходную строку
- ; lpDst - указатель на буфер для полученной строки
- ; lpPattern - указатель на заменяемую подстроку
- ; lpReplace - указатель на строку для замены
- ; dNum - количество замен (0 - заменить все)
- ;-----------------------------------------------------
- proc _replace lpSrc:DWORD, lpPattern:DWORD, lpReplace:DWORD,\
- lpDst:DWORD, dNum:DWORD
- pusha
- ; Указатель на буфер-приемник
- mov edx,[lpDst]
- ; Счетчик замен
- xor ebx,ebx
- ; Исходная строка не пустая?
- mov ecx,[lpSrc]
- cmp byte [ecx],0
- jz .loc_ret
- ; Заменяемая строка не пустая?
- mov eax,[lpPattern]
- cmp byte [eax],0
- jz .loc_copy_all
- .loc_scan:
- mov esi,ecx
- mov edi,[lpPattern]
- ; Исходная строка закончилась?
- cmp byte [esi],0
- je .loc_end_replace
- @@:
- ; Строки совпали с паттерном?
- cmp byte [edi],0
- je .loc_move_replace
- ; Символ совпадает с
- lodsb
- ; Заменять все вхождения?
- cmp [dNum],0
- je .loc_skip_counter
- ; Уже заменили нужное количество?
- cmp ebx,[dNum]
- je .loc_move_one_char
- .loc_skip_counter:
- cmp al,byte [edi]
- jne .loc_move_one_char
- inc edi
- jmp @b
- .loc_move_replace:
- ; Увеличить счетчик замен
- inc ebx
- mov ecx,esi
- ; Записать заменяющую строку
- mov esi,[lpReplace]
- mov edi,edx
- @@:
- lodsb
- or al,al
- jz .loc_scan
- stosb
- inc edx
- jmp @b
- .loc_move_one_char:
- ; Скопировать один символ
- mov al,byte [ecx]
- mov byte [edx],al
- inc edx
- inc ecx
- jmp .loc_scan
- .loc_end_replace:
- ; Записать финальный 0 в строку
- mov byte [edx],0
- jmp .loc_ret
- .loc_copy_all:
- ; Просто скопировать исходную строку
- mov esi,[lpSrc]
- mov edi,[lpDst]
- @@:
- lodsb
- stosb
- or al,al
- jnz @b
- .loc_ret:
- popa
- ret
- endp
Теперь несколько примеров использования. Сперва в сегменте данных определим все необходимое, а именно исходную строку, строки для поиска и замены, а также буфер-приемник результата.
Code (Assembler) : Убрать нумерацию
- section '.data' data readable writeable
- ...
- ; Строка для поиска
- szStr1 db 'FASM',0
- ; Строка для замены
- szStr2 db 'Flat Assembler',0
- ; Исходная строка
- buff1 db 'FASM - Fast and Simply!',13,10
- db 'I Like FASM!',13,10
- db 'FASM the Best!',0
- ; Буфер-приемник результата
- buff2 rb 1000h
Code (Assembler) : Убрать нумерацию
- ; Заменить только первое вхождение
- stdcall _replace,buff1,szStr1,szStr2,buff2,1
- ...
- ; Заменить все вхождения
- stdcall _replace,buff1,szStr1,szStr2,buff2,0
Просмотров: 11543 | Комментариев: 8
Метки: Assembler, полезные функции
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
brute
(07.04.2012 в 05:33):
есть функция "заменить всё - ReplaceString", а чтобы сделать определённое количество замен - такого нет: ReplaceString("строка","что найти","на что заменить",["учитывать ли регистр",["с какой позиции начать искать"]). Я код скрипта привёл, чтобы сравнить размер кода, понятность-читаемость и размер бинарника...
ManHunter
(06.04.2012 в 07:29):
А на бейсике разве нет штатных функций замены?
brute
(06.04.2012 в 06:13):
то же на PB: http://webfile.ru/5898434
ManHunter
(29.03.2012 в 17:07):
То получится неплохая оптимизация по размеру и быстродействию :) Спасибо!
zummenix
(29.03.2012 в 17:05):
А если переменные dSPos и dDPos заменить на регистры ecx и edx?
Voffka
(28.03.2012 в 12:02):
Это я к тому что такая функция на ассемблере есть, а уж на каком это второй вопрос.
ManHunter
(28.03.2012 в 11:21):
Я не пишу на MASM, и даже не планирую начинать. Тем более, что в szRep нет счетчика замен.
Voffka
(28.03.2012 в 11:20):
В масме такая функа есть szRep называется.
Добавить комментарий
Заполните форму для добавления комментария