(MASM) Удаление второй подстроки из первой и сохранение результата третью - Assembler
Формулировка задачи:
Здравствуйте! Три дня ломал голову над задачей и все-таки решил прибегнуть к вашей помощи.
Даны три строки, S1, S2, S3. Удалить из S1 первое появление S2, остаточную строку записать в S3. Вывести все три строки.
Вот мои безуспешные попытки
include Irvine32.inc Show macro string lea edx, string call WriteString call Crlf endm .data S1 db '3331234222222453322222222345',0 S2 db '345',0 S3 db sizeof S1 dup(0) len_S2 dd ? len_S1 dd ? s3_edi dd ? .code main proc Show S1 ;lab S1, S2, S3 cld mov edi, offset S2 Invoke Str_length, edi mov len_S2, eax mov edi, offset S1 Invoke Str_length, edi mov len_S1, eax lea edi, S3 mov s3_edi, edi lea esi, S1 lea edi, S2 srch: lea edi, S2 mov ecx, len_S2 repe cmpsb jne mismatch jmp ext mismatch: pusha dec esi dec edi lodsb mov edi, s3_edi stosb popa inc s3_edi jmp srch ext: Show S2 Show S3 exit main endp end main
Решение задачи: «(MASM) Удаление второй подстроки из первой и сохранение результата третью»
textual
Листинг программы
org 100h jmp start Str1 db 'ANBC-HD*G_HJV0125800 BKMC4 NX3451185ABCGEF00245',0 len1 = ($ - Str1)-1 ; длина строки (без нуль-терминала) Str2 db '345',0 len2 = ($ - Str2)-1 Str3 db 80 dup(0) crlf db 13,10,'$' start: mov bx,len1 ; BX = длина строки xor ax,ax ; плавающая позиция xor dx,dx ; это будет найденая позиция в строке @@: ; mov si,Str1 ; указатель на строку mov di,Str2 ; ..и на под/строку mov cx,len2 ; длина под/строки add si,ax ; добавляем плавающую позицию mov dx,si ; запоминаем эту позицию repe cmpsb ; сравниваем строки jz @f ; переход, если есть вхождение inc ax ; иначе: позиция поплыла вперёд dec bx ; ..а счётчик назад jnz @b ; если не конец строки, то циклимся.. ; ошибка поиска! ====================================================// mov al,7 ; бипер, int 29h ; jmp exit ; ..и на выход! ; Есть вхождение! ; На этом этапе SI установлен на первом/найденном символе, плюс длина под/строки. ; DX указывает на первый/найденный символ. @@: ; mov di,dx ; вставляем по-адресу DX, xor al,al ; ..нуль-терминал (отрезали хвост). stosb ; lea cx,[Str1+len1] ; вычисляем длину хвоста sub cx,dx ; sub cx,len2 ; ..без под/строки mov di,Str3 ; DI приёмник, SI источник rep movsb ; копируем СХ-байт из SI в DI mov si,Str1 ; выводим на экран получившиеся строки call WriteString ; эта функция выводит строку на консоль (по-байтно), mov si,Str2 ; ..пока не встретится нуль-терминал. call WriteString ; mov si,Str3 ; call WriteString ; exit: ; xor ax,ax ; int 16h ; int 20h ; на выход! ;ннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн WriteString: ; mov dx,crlf ; курсор на новую строку mov ah,9 ; int 21h ; @@: ; lodsb ; читаем байт из SI or al,al ; нуль-терминал? jz @f ; int 29h ; нет - печатаем символ. jmp @b ; @@: ; ret ;
Объяснение кода листинга программы
Код на языке Assembler выполняет удаление второй подстроки из первой и сохранение результата третьей. Список действий:
- Переменная
len1
содержит длину строкиStr1
(включая нуль-терминал), вычисленную как разность междуStr1
и нуль-терминалом. - Переменная
len2
содержит длину подстрокиStr2
, вычисленную как разность междуStr2
и нуль-терминалом. - Переменная
Str3
содержит результат, который будет отправлен на консоль. - В цикле сравниваются символы строки
Str1
и подстрокиStr2
. Если символы совпадают, то увеличивается счётчик совпадений в регистреbx
. - Если счётчик совпадений равен нулю, то регистры
si
иdi
инкрементируются на длину подстроки, и цикл продолжается. - Если счётчик совпадений не равен нулю, то увеличивается регистр
ax
, который является плавающей позицией в строке. - Делается переход на начало цикла, чтобы продолжить поиск совпадений.
- Если счётчик совпадений равен нулю, то делается переход на выход из программы.
- Если счётчик совпадений не равен нулю, то происходит копирование символов из строки
Str1
в строкуStr3
. - Выводится на консоль строка
Str3
.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д