Найти порядковый номер ключевого слова в строке - 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