Найти порядковый номер ключевого слова в строке - Assembler

Узнай цену своей работы

Формулировка задачи:

Задание собственно такое такое: Есть последовательность слов, которые вводятся через пробелы с клавиатуры (я записываю это все в массив). Затем с клавиатуры вводится ключевое слово и необходимо найти это слово в последовательности и вывести сообщение в зависимости от результата: "Такого слова нет" или " Слово номер N", где N порядковый номер слова. Вот наброски кода, не работает цикл, не могу исправить. Подскажите пожалуйста.
.model small;
.stack 100h;
.data
 
i dw 0h
Stg     db     100h dup(0h);
String     db     ': $' 
mess1     db     0dh,0ah,"Enter first string",0dh,0ah,"$"
mess2     db     0dh,0ah,"Enter second string",0dh,0ah,"$"
str1     db     10, ?, 9 dup (?)
max        dw    ?
chislo    dw    ?
 
.code
Start:
    mov ax, @data
    mov ds, ax
    lea dx, mess1
    mov ah, 09h
    int 21h ;приглашение к вводу строки 1
 
    ; Ввод первой строки
    lea dx, str1
    mov ah, 0ah
    int 21h
 
    xor dx,dx
    mov ah, 09h
    Lea dx, mess2
    int 21h 
    mov ah, 1h;  Ф-я ввода символа
    mov si, 0h
    mov bx, 0h
    Input:   ;Ввод массива
    int 21h
    mov cx, si
    mov Stg[bx], cl;     Длина слова
    cmp al, 32;  Проверка на пробел
    jne Skip1
    mov si, 0h
    add bx, 10h;     Начало следующего слова
    jmp Input
    Skip1:
    inc si
    mov Stg[bx+si], al;  Помещение символа в массив 
    cmp al, 13
    jne Input
    mov Stg[bx+si], 0h;  Удаление Enter'а
    mov i, bx;   Кол-во слов
    mov bx, 0h
 
find proc
    xor bx, bx
    lea bx, Stg
    xor ax, ax
    mov ax, [bx]
    mov max, ax
    mov cx, i
    xor dx, dx
    mov al, str1
cicl:
    mov ax,[bx]
    cmp al, ax
    inc bx
    jne cicl
    mov chislo,si
    lea dx, chislo
    mov ah, 09h
    int 21h
 
find endp
End Start

Решение задачи: «Найти порядковый номер ключевого слова в строке»

textual
Листинг программы
.model small
 
.stack 100h
 
.data
        DelimChar       db      ' '     ;символ, разделитель слов
        asPromptStr     db      'Enter a string:', 0Dh, 0Ah, '$'
        asPromptWord    db      'Enter a word:', 0Dh, 0Ah, '$'
        asResultYes     db      'Слово номер ', '$'
        asResultNo      db      'Такого слова нет', '$'
        CrLf            db      0Dh, 0Ah, '$'
        msgPressAnyKey  db      0Dh, 0Ah, 'Press any key to exit...', '$'
        String          db      80, ?, 81 dup(?)
        asWord          db      80, ?, 81 dup(?)
        N               dw      ?
.code
 
main    proc
        ;инициализация сегментного регистра ds адресом сегмента данных
        mov     ax,     @data
        mov     ds,     ax
 
        mov     ah,     09h
        lea     dx,     [asPromptStr]
        int     21h
        mov     ah,     0Ah
        lea     dx,     [String]
        int     21h
        mov     ah,     09h
        lea     dx,     [CrLf]
        int     21h
 
        mov     ah,     09h
        lea     dx,     [asPromptWord]
        int     21h
        mov     ah,     0Ah
        lea     dx,     [asWord]
        int     21h
        mov     ah,     09h
        lea     dx,     [CrLf]
        int     21h
 
        ;подготовка к выполнению строковых цепочечных команд
        cld
        mov     ax,     ds
        mov     es,     ax
 
        lea     si,     [String+2]
        xor     cx,     cx
        mov     cl,     [String+1]
        mov     [N],    0               ;признак - слово не найдено
        xor     dx,     dx              ;счётчик выделенных слов
        jcxz    @@Break
        @@ForEachWord:
                ;выделяем слово
                call    GetNextWord
                jcxz    @@Break
 
                inc     dx
                ;сравнение выделенного слова с искомым
                push    si
                push    cx
                push    bx
 
                mov     si,     si              ;первая строка
                mov     cx,     bx
                lea     di,     [asWord+2]      ;вторая строка
                xor     bx,     bx
                mov     bl,     [asWord+1]
                call    SCmp
                ;восстановление контекста поиска
                pop     bx
                pop     cx
                pop     si
                jne     @@SearchNext
                        mov     [N],    dx
                        jmp     @@Break
        @@SearchNext:
                ;переход к разделителю после слова
                add     si,     bx
                sub     cx,     bx
 
        jnz     @@ForEachWord
@@Break:
 
        cmp     [N],    0
        je      @@ResultNo
        mov     ah,     09h
        lea     dx,     [asResultYes]
        int     21h
        mov     ax,     [N]
        aam
        add     ax,     '00'
        mov     dl,     ah
        mov     dh,     al
        mov     ah,     02h
        int     21h
        mov     dl,     dh
        int     21h
        jmp     @@Wait
@@ResultNo:
        mov     ah,     09h
        lea     dx,     [asResultYes]
        int     21h
@@Wait:
        ;ожидание нажатия любой клавиши
        mov     ah,     09h
        lea     dx,     [msgPressAnyKey]
        int     21h
 
        mov     ah,     00h
        int     16h
 
        mov     ax,     4C00h
        int     21h
main    endp
 
;сравнение двух строк
;на входе:
; ds:si - адрес первой строки
; cx    - длина первой строки
; ds:di - адрес второй строки
; bx    - длина второй строки
;на выходе:
;  CY=1 ZF=0, при S1<S2
;  CY=0 ZF=1, при S1=S2
;  CY=0 ZF=0, при S1>S2
SCmp    proc
        push    ax
        push    bx
        push    cx
        push    dx
        push    si
        push    di
        push    es
 
        push    ds
        pop     es
 
        ;ax=cx=len1
        ;cx=min(len1, len2)
        ;bx=len2-min(len1, len2)=0 или разность длин
        push    cx
        push    bx
        sub     bx,     cx
        sbb     ax,     ax
        and     ax,     bx
        add     cx,     ax
        pop     bx
        pop     ax
        sub     bx,     ax
        ;сравнить подстроки минимальной длины
        repe    cmpsb
        jnz     @@scExit
@@scCmpLen:
        ;если подстроки равны, то проверить длины
        xor     ax,     ax
        cmp     ax,     bx
@@scExit:
        pop     es
        pop     di
        pop     si
        pop     dx
        pop     cx
        pop     bx
        pop     ax
        ret
SCmp    endp
 
;перейти к следующему слову в строке
;на входе:
; ds:si - адрес строки
; cx    - длина строки
;на выходе:
; ds:si - адрес первого символа слова в строке
; cx    - длина строки от первого символа нового слова
; bx    - длина найденного слова
GetNextWord     proc
        push    ax
        ;push   bx
        ;push   cx
        push    dx
        ;push   si
        push    di
        push    es
        xor     bx,     bx
        jcxz    @@gnwExit
        mov     al,     [DelimChar]
        ;пропуск разделителей (пробелов)
        @@SkipDelimiters:
                cmp     al,     [si]
                jne     @@NewWord
                inc     si
        loop    @@SkipDelimiters
        jcxz    @@gnwExit       ;если строка закончилась - выйти
        ;найдено новое слово
@@NewWord:
        ;пропускаем все буквы слова до разделителя
        ;вычисляем длину слова
        push    cx
        mov     di,     si
        xor     bx,     bx              ;bx - длина очередного слова
        @@WhileWord:
                cmp     al,     [di]
                je      @@gnwBreak
                inc     bx              ;увеличиваем длину слова
                inc     di              ;переходим к следующему символу
        loop    @@WhileWord
@@gnwBreak:
        pop     cx
@@gnwExit:
        push    ds
        pop     es
        pop     es
        pop     di
        ;pop    si
        pop     dx
        ;pop    cx
        ;pop    bx
        pop     ax
        ret
GetNextWord     endp
 
end     main

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

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