Ввести строку. Вывести слова, содержащие букву «о» и количество таких слов - Assembler
Формулировка задачи:
Здравствуйте, есть задание по написанию программы на ассемблере для консоли. Перелазила почти весь Интернет, просмотрела ваш форум, но ничего не помогло. Нашла кусочек программы, разбиралась в нем часов 5, пыталась переделать под свою, но тоже ничего не вышло.
Вот кусочек кода:
Не понимаю, как организовать поиск пробела и переход к следующему слову (строки 18-25), а также как организовать в строках 11-13 поиск символа в слове не с начала строки, а во всем слове. Помогите, пожалуйста. Совсем потеряла надежду разобраться
m2: mov eax, Len ;длину строки в счетчик lea ebx, BUF ;начало строки в ebx lea edx, Rez ;начало строки в edx dec ebx m3: cmp eax, 2 ;не равен ли счетчик 0 je FAILED ;равен=> к метке exit dec eax ;ecx - 1 (смещение) inc ebx ;ebx + 1 (смещение) mov al, [ebx] ;в регистр содержимое ячейки из строки cmp al, 'r' ;сравниваем с "r" je m4 ;равен,переходим к метке m4 cmp al, ' ' ;сравниваем с пробелом je m3 ;равен пробелу,переходим к метке m3 inc ebx ;перешли к след элементу строки cld ;cбросили флаг,идем слева направо mov al, ' ' ;в регистр записываем пробел mov edi, ebx ;в edi записываем ebx repne scasb ;пока не встретится пробел сравниваем dec edi ; ;нашли пробел,получили его смещение mov ebx, edi ;записали в ebx текущую позицию пробела jmp m3 ;в метку m3 m4: ;записываем слово начинающееся на букву 'r' в строку Rez mov esi, ebx ;для lodsb mov edi, edx ;для stosb cld n1: lodsb ;из esi символ в al mov ebx, edi cmp al, ' ' je m5 ;если дошли до пробела, то слово закончилось,в метку m5 stosb ;символ al в edi loop n1 ;цикл m5: inc COUNT ;увеличили переменную, отвеч. за кол-во слов stosb ;запишем пробел в строку rez чтобы слова были разделены mov edx, edi ;текущее смещение в dx dec eax ;уменьшили счетчик jmp m3
Решение задачи: «Ввести строку. Вывести слова, содержащие букву «о» и количество таких слов»
textual
Листинг программы
;FASM-code... format PE Console 4.0 include 'win32a.inc' entry start section '.data' data readable writeable mes db 'Type string: ' stdOut dd 0 ;место под хэндлы ввода-вывода stdIn dd 0 ; size dd 0 ;длина строки buff db 128 dup(0) ;буфер для строки (макс.128-символов) table dd 32 dup(0) ;таблица с адресами начала слов (макс.16-слов) section '.text' code readable executable start: invoke GetStdHandle, -11 ;получаем хэндлы консоли mov [stdOut], eax ;(монитор invoke GetStdHandle, -10 ; ..и клава) mov [stdIn], eax ;------ Запрос на ввод, и вводим строку invoke WriteConsoleA, [stdOut], mes, 13,0,0 invoke ReadConsoleA, [stdIn], buff, 128, size, 0 ;------ Создаём таблицу адресов начала и длины каждого слова в строке mov edi,buff ; адрес строки mov ecx,[size] ; её длина xor esi,esi ; смещение в таблице mov ebp,1 ; счётчик слов (1 в дефолте) mov al,' ' ; что искать @findSpace: ; mov ebx,ecx ; BX = длина от начала mov dword[table+esi],edi ; запишем в таблицу адрес начала слова add si,4 ; ..(шаг вправо в таблице) repne scasb ; искать пробел в строке! sub ebx,ecx ; вычисляем длину слова mov dword[table+esi],ebx ; запишем её в таблицу add si,4 ; ..(шаг вправо) inc ebp ; увеличиваем счётчик слов or ecx,ecx ; всю строку проверили? jnz @findSpace ; переход, если нет.. ;------ Поиск в каждом слове символа(о), и вывод этого слова на консоль ; адрес слов и их длину будем брать из таблицы. ; BP = кол-во указателей в таблице (общее кол-во слов в строке). mov esi,table ; адрес таблицы в SI @findChar: dec ebp ; все слова проверили? jz @exit ; выйти, если да.. lodsd ; xchg edi,eax ; EDI = адрес начала очередного слова lodsd ; xchg ecx,eax ; ECX = длина этого слова push ecx edi ; запомнить для вывода на консоль! ; mov al,'o' ; что искать в слове.. repne scasb ; поиск! or cx,cx ; запомним результат поиска во-флагах pop edi ecx ; снимаем со-стека атрибуты слова jz @findChar ; проверить флаги! ; ..следующее слово (если нет результата). invoke WriteConsoleA, [stdOut],edi,ecx,0,0 ; иначе: отправляем атрибуты слова, jmp @findChar ; ..в параметры функции вывода на экран. @exit: invoke ExitProcess, 0 ; выход из программы! ;--------------------------------------------------------------------------- section '.idata' import data readable library kernel, 'KERNEL32.DLL' import kernel,\ WriteConsoleA,'WriteConsoleA',\ ; API для импорта из кернел32. ReadConsoleA,'ReadConsoleA',\ GetStdHandle,'GetStdHandle',\ ExitProcess, 'ExitProcess'
Объяснение кода листинга программы
Код написан на ассемблере и решает задачу поиска слов, содержащих букву о
, и вывода этих слов вместе с их количеством.
Список действий:
- Получение хэндлов для консоли и клавиатуры.
- Запрос на ввод строки.
- Создание таблицы адресов начала и длины каждого слова в строке.
- Поиск в каждом слове символа
о
и вывод этого слова на консоль. - В конце программы выводится количество найденных слов.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д