На главную
ПРАВИЛА FAQ Помощь Участники Календарь Избранное DigiMania RSS
msm.ru
! Перед отправкой сообщения внимательно прочтите правила раздела!!!
1. Запрещается обсуждать написание вирусов, троянов и других вредоносных программ!
2. Для обсуждения создания операционных систем (ОС) используйте раздел Обсуждаем новые идеи.

3. Настоятельно рекомендую обратить особое внимание на правила форума, которые нарушаются чаще всего:
  3.1. Перед созданием темы просмотрите FAQ раздела Assembler и Полезные ссылки.
  3.2. Заголовок темы должен кратко отражать её суть. Темы с заголовками типа "Срочно помогите!" или "В чём проблема?" будут отправляться в Корзину для мусора.
  3.3. Исходники программ обязательно выделяйте тегами [code]...[/code] (одиночные инструкции можно не выделять).

Не забывайте также про главные ПРАВИЛА ФОРУМА!
Участники форума, нарушающие правила, будут наказываться, а вносящие вклад в развитие форума - награждаться (DigiMoney и прочими радостями).

Приятного вам общения! ;)
Модераторы: Jin X, Qraizer
Страницы: (2) [1] 2  все  ( Перейти к последнему сообщению )  
> Поиск одинаковых слов в строках, Вопрос по TASM
Всем привет!
Есть код из книги Юрова по ассемблеру
ExpandedWrap disabled
    ;prg_12_4.asm
    MASM
    MODEL   small
    STACK   256
    .data
    ;строки для сравнения
    string1 db  'Поиск символа в этой строке.',0ah,0dh,'$'
    string2 db  'Поиск символа не в этой строке.',0ah,0dh,'$'
    mes_eq  db  'Строки совпадают.',0ah,0dh,'$'
    fnd db  'Несовпавший элемент в регистре al',0ah,0dh,'$'
    .code
    ;привязка ds и es к сегменту данных
    assume ds:@data,es:@data
    main:
        mov ax,@data    ;загрузка сегментных регистров
        mov ds,ax
        mov es,ax       ;настройка es на ds
        mov ah,09h
        lea dx,string1
        int 21h ;вывод string1
        lea dx,string2
        int 21h ;вывод string2
        cld     ;сброс флага df
        lea di,string1  ;загрузка в es:di смещения
    ;строки string1
        lea si,string2  ;загрузка в ds:si смещения
    ;строки string2
        mov cx,29   ;для префикса repe - длина строки
    ;поиск в строке (пока нужный символ и символ в строке не равны)
    ;выход - при первом несовпавшем
    repe    cmps    string1,string2
        jcxz    eql ;если равны - переход на eql
        jmp no_eq   ;если не равны - переход на no_eq
    eql:        ;выводим сообщение о совпадении строк
        mov ah,09h
        lea dx,mes_eq
        int 21h ;вывод сообщения mes_eq
        jmp exit        ;на выход
    no_eq:      ;обработка несовпадения элементов
        mov ah,09h
        lea dx,fnd
        int 21h ;вывод сообщения fnd
    ;теперь, чтобы извлечь несовпавший элемент из строки
    ;в регистр-аккумулятор,
    ;уменьшаем значение регистра si и тем самым перемещаемся
    ;к действительной позиции элемента в строке
        dec si  ;команда lods использует ds:si-адресацию
    ;теперь ds:si указывает на позицию в string2
        lods    string2 ;загрузим элемент из строки в AL
    ;нетрудно догадаться, что в нашем примере это символ - "н"
    exit:       ;выход
        mov ax,4c00h
        int 21h
    end main


Результатом его работы является первая символ (подстрока), который не совпадает со строкой образцом. Он заносится в регистр AL, это понятно.
А как нужно изменить данный код таким образом, чтобы он выводил все подстроки (слова) данной строки, которые одинаковы для обеих строк?
Не соображу :crazy:
Цитата APleskan @
чтобы он выводил все подстроки (слова) данной строки, которые одинаковы для обеих строк

Нипанятна... покажите хотя бы эталонный вывод для строк из кода.
Есть претензии ко мне как к модератору? читайте Правила, разделы 5 и 6, и действуйте соответственно.
Есть претензии ко мне как к участнику? да ради бога.
Не нравятся мои ответы? не читайте их.
В общем, берегите себя. Нервные клетки не восстанавливаются.
Проще говоря нужно сравнить две строки на предмет нахождения в них одинаковых слов.
Вот так :D
Понятнее не стало. Покажи, что хочешь получить на экране, если в код внести нужные тебе исправления.

В текущем виде при запуске должно получиться нечто вроде:
ExpandedWrap disabled
    c:\> prg_12_4
     
    Поиск символа в этой строке.
    Поиск символа не в этой строке.
    Несовпавший элемент в регистре al
     
    c:\>
Есть претензии ко мне как к модератору? читайте Правила, разделы 5 и 6, и действуйте соответственно.
Есть претензии ко мне как к участнику? да ради бога.
Не нравятся мои ответы? не читайте их.
В общем, берегите себя. Нервные клетки не восстанавливаются.
Этот выхлоп есть. Нужно получить, например, для двух строк: красное яблоко и зелёное яблоко результат яблоко.
:)

P.S. Понятно, что лучше городить макросы, но как это делать для таких динозавров я давно и основательно позабыл :-?
Сообщение отредактировано: APleskan -
Это будет совсем другой код :)
В общих чертах: перебираешь каждое слово первой строки и ищешь эти слова во второй. Если нашёл, выводишь :)
Tell me would you kill to save a life?
Tell me would you kill to prove you're right?
Crash, crash, burn, let it all burn
This hurricane's chasing us all underground...
Насколько я понимаю, без разбиения на отдельные процедуры здесь не обойтись?
Я бы сделал так:
ExpandedWrap disabled
    String1 db 'Hello my big boss!',0
    String2 db 'Good bye my little boss!',0
    First dw String1
    Second dw String2
First - текущая позиция строки String1, Second - строки String2.
И дальше нужна процедура NextWord, которая переходит к следующему слову (в регистре BX, скажем, ей передаётся адрес переменной с текущей позицией строки), т.е.:
ExpandedWrap disabled
    CompareNext:
      . . .
      lea bx,First
      call NextWord
      jnc CompareNext
    . . .
    NextWord proc
      mov si,[bx]
    . . .
процедура будет переходить к следующему слову (т.е. пропускать сначала все буквенные символы, затем все небуквенные). Если встретит в итоге 0 (конец строки), вернёт флаг CF=1 (stc), иначе CF=0 (clc).

Ну и нужна будет функция, сравнивающая оба слова (из First и Second) и ещё процедура, выводящая текущее слово (из First) + пробел.
Tell me would you kill to save a life?
Tell me would you kill to prove you're right?
Crash, crash, burn, let it all burn
This hurricane's chasing us all underground...
Спасибо за наводку. Попробую довести до ума ;)
M

APleskan, кстати, тему надо называть не креативно, как роман, а соответственно сути вопроса!
Tell me would you kill to save a life?
Tell me would you kill to prove you're right?
Crash, crash, burn, let it all burn
This hurricane's chasing us all underground...
На процедуры можно, конечно, не бить - но лапша же получится...

И учти, что для каждого слова первой строки тебе надо будет проверять совпадение со всеми словами второй строки. Так что начни с написания процедуры поиска одного слова в строке, а потом добавишь обвязку перебора слов.

И для упрощения я бы сначала в обеих строках заменил все разделители слов на некий один и тот же символ, который в строке гарантированно отсутствует. Совсем отлично, если это будет символ доллара - упростит вывод.
Есть претензии ко мне как к модератору? читайте Правила, разделы 5 и 6, и действуйте соответственно.
Есть претензии ко мне как к участнику? да ради бога.
Не нравятся мои ответы? не читайте их.
В общем, берегите себя. Нервные клетки не восстанавливаются.
Всем спасибо за ответы.

У меня обширная электронная библиотека. Есть еще Ирвин Кип, ;) так что, в любом случае чего-нибудь да сварганю :rolleyes:

Добавлено
Кстати да, я старею. У того же Юрова в "Практикуме" есть решение похожей задачи 8-)
Jin X можете сносить тред :ph34r:
Оставлю здесь частное решение задачи, авось кому-то пригодится :)
ExpandedWrap disabled
    ;--------------------------------------------------------------------------------;
    ;search.asm - поиск строки P в строке S. Длина S фиксирована.
    ;Вход: S и P - массивы символов размером N и M байт (M=<N).
    ;Выход: сообщение о количестве вхождений строки P в строку S.
    ;--------------------------------------------------------------------------------;
    masm
    model small
    .data
    ;задаем массив S
    s   db  "яблоко красное, зеленое яблоко, яблоко сладкое, кислое яблоко, яблоко летнее, спелое яблоко"
    Len_S=$-s
        Db  "$"
    mes db  "Вхождений строки - "
    ;задаем массив P - аргумент поиска
    p   db  "зеленое яблоко"
    Len_P=$-p
        db  " - "
    Count   db  0,"$"   ;счетчик вхождений P в S
    .stack  256
    .486
    .code
    main:
        mov dx,@data
        mov ds,dx
    push    ds
    pop es
        cld
        mov cx,len_s
        lea di,s
        mov al,p    ;P[0]->al
    next_search:
        lea si,p
        inc si  ;на следующий символ
    repne   scasb
        jcxz    exit
    push    cx
        mov cx,len_p-1
    repe    cmpsb
        jz  eq_substr
    ;строка p <> подстроке в s
        mov bx,len_p-1
        sub bx,cx
    pop cx
        sub cx,bx   ;учли пройденное при сравнении cmpsb
        jmp next_search
    eq_substr:
    ;далее можно выйти, если поиск однократный, но мы упорные, поэтому продолжаем
    pop cx
        sub cx,len_p-1  ;учли пройденное при сравнении cmpsb
        inc count
        jmp next_search
     
    exit:  
        add count,30h ;преобразуем число в строку
        lea dx,mes
        mov ah,9h
        int 21h
        
    ;выход
        mov ax,4c00h
        int 21h
    end main

Доработка приветствуется :thanks:
ExpandedWrap disabled
    s db 15 dup("aa ")
    ...
    p db "aa"
Упс...

ExpandedWrap disabled
    s db "ababac"
    ...
    p db "abaс"
Упс-2...

ExpandedWrap disabled
            mov     dx,@data
            mov     ds,dx
    push    ds
    pop     es

А почему не
ExpandedWrap disabled
            mov     dx,@data
            mov     ds,dx
            mov     es,dx
?

И за каким тут
ExpandedWrap disabled
    .486
?
Есть претензии ко мне как к модератору? читайте Правила, разделы 5 и 6, и действуйте соответственно.
Есть претензии ко мне как к участнику? да ради бога.
Не нравятся мои ответы? не читайте их.
В общем, берегите себя. Нервные клетки не восстанавливаются.
Можно смоделировать 2-х проходной алгоритм:

1) Находится первый, последний символ текущего слова и расстояние (длина слова) в первой строке
2) Ищется тоже самое во второй строке
3) Если все совпадает - вторым проходом сравниваются слова на полное совпадение

Во многих случаях - можно получить прирост скорости сравнения. Т.к. получается некое подобие сравнивания не данных, а такого вот примитивного хэша. Естественно - в некоторых случаях это может наоборот притормозить. Чуйка подсказывает, что для обработки естественного текста подход будет полезен.
Мои программные ништякиhttp://majestio.info
1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
0 пользователей:


[ Script Execution time: 0,1496 ]   [ 19 queries used ]   [ Generated: 24.05.17, 09:50 GMT ]