Замена символов - Assembler
Формулировка задачи:
Помогите разобраться. Вот задание лабы: Задано текст із 20 символів. Визначити кількість повторень поєднань "ОР" в тексті і замінити такі повторення символом "!". Подскажите как сделать замену символов.
Есть код программы замены символов, но проблема в том, что заменяется только первый встретившийся нужный символ.
.386 ; директива визначення типу мікропроцесора
.model flat,stdcall ; завдання лінійної моделі пам’яті та угоди ОС Windows
option casemap:none ; відмінність малих та великих літер
include \masm32\include\windows.inc ; файли структур, констант …
include \masm32\include\kernel32.inc ; файли систем. функцій застосувань…
include \masm32\include\user32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
.data ; директива визначення даних
titl db " Результат ",0 ; назва вікна
mas1 db 'assembler' ; масив байтів із символами коду ASCII
len equ $-mas1 ; визначення кількості байтів в масиві mas1
buf db ?,0 ; буфер виведення повідомлення
.code ; директива початку сегмента даних
_st: ; мітка початку програми з ім’ям _st
lea edi, mas1 ; завантаження адреси масиву mas1
mov al, 's' ; завантаження символу ‘f’
mov ecx, len ; встановити в лічильник max значення літер
cld ; напрям – вгору
repne scasb ; повторювати, поки не буде дорівнювати
dec edi ; знайдений: декременувати DI
MOV BYTE PTR[edi],' '
invoke MessageBox, \ ; АРІ-функція виведення спрощеного віконця
NULL, \ ; hwnd – ідентифікатор вікна
addr mas1, \ ; адреса рядка, яка містить текст повідомлення
addr titl, \ ; адреса рядка, яка містить заголовок повідомлення
MB_OK ; вигляд діалогового вікна – одна кнопка ОК
invoke ExitProcess,0 ; виклик процедури повернення керування
; ОС Windows та визволення ресурсів
end _st ; директива закінчення програми з ім’ям _st
Решение задачи: «Замена символов»
textual
Листинг программы
format PE console include 'win32a.inc' mov esi,ssk mov edi,sk mov ecx,[qcsk] sub ecx,[qcssk] inc ecx mov ebx,0 mRun: push esi push edi push ecx mov ecx,[qcssk] mov al,1 mCompare: mov ah,[edi] cmp [esi],ah je mEqual mov al,0 jmp mCompareExit mEqual: inc esi inc edi loop mCompare inc ebx mCompareExit: pop ecx pop edi pop esi cmp al,1 jne mNot push esi push edi push ecx mov esi,edi inc esi repne movsb pop ecx pop edi pop esi mov [edi],byte 33 dec ecx mNot: inc edi cmp ecx,0 jne mEcxNZ inc ecx mEcxNZ: loop mRun invoke ExitProcess,0 sk db 'OPcdefOPxyzOP' qcsk dd $-sk ssk db 'OP' qcssk dd $-ssk include 'API\kernel32.inc' data import library kernel32,'KERNEL32.DLL' end data
Объяснение кода листинга программы
Список элементов кода:
- Переменные:
- esi, ssk
- edi, sk
- ecx, [qcsk]
- ebx, 0
- Циклы:
- while (1) {...} - mRun
- while (esi < [qcssk]) {...} - mCompare
- while (ecx != 0) {...} - mEcxNZ
- Команды:
- mov
- push
- pop
- cmp
- jne
- inc
- repne
- movsb
- invoke
- db (данные, представленные в виде строки)
- dd (данные, представленные в виде двойного слова)
- library (импорт функций из библиотеки kernel32.dll)
- Значения переменных:
- ssk содержит 'OP'
- qcssk содержит '-ssk'
- qcsk содержит 'OPcdefOPxyzOP'
- ebx содержит 0
- ecx содержит количество символов, которые нужно заменить
- edi содержит индекс текущего символа для замены
- esi содержит индекс последнего символа для замены
- al содержит 0 или 1
- Последовательность выполнения команд:
- Переменная ecx инициализируется значением из qcsk
- Выполняется цикл mCompare, пока не будет найдено соответствие символа из ssk
- Если символ найден, индексы esi и edi увеличиваются, и выполняется цикл mRun
- Если символ не найден, выполняется цикл mEcxNZ, пока ecx не станет равным 0
- Если ecx не равно 0, вызывается функция ExitProcess с аргументом 0
- Если ecx равно 0, вызывается функция ExitProcess с аргументом 0