(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 выполняет удаление второй подстроки из первой и сохранение результата третьей. Список действий:

  1. Переменная len1 содержит длину строки Str1 (включая нуль-терминал), вычисленную как разность между Str1 и нуль-терминалом.
  2. Переменная len2 содержит длину подстроки Str2, вычисленную как разность между Str2 и нуль-терминалом.
  3. Переменная Str3 содержит результат, который будет отправлен на консоль.
  4. В цикле сравниваются символы строки Str1 и подстроки Str2. Если символы совпадают, то увеличивается счётчик совпадений в регистре bx.
  5. Если счётчик совпадений равен нулю, то регистры si и di инкрементируются на длину подстроки, и цикл продолжается.
  6. Если счётчик совпадений не равен нулю, то увеличивается регистр ax, который является плавающей позицией в строке.
  7. Делается переход на начало цикла, чтобы продолжить поиск совпадений.
  8. Если счётчик совпадений равен нулю, то делается переход на выход из программы.
  9. Если счётчик совпадений не равен нулю, то происходит копирование символов из строки Str1 в строку Str3.
  10. Выводится на консоль строка Str3.

Оцени полезность:

13   голосов , оценка 4.077 из 5
Похожие ответы