Ввести строку. Вывести слова, содержащие букву «о» и количество таких слов - 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'
Объяснение кода листинга программы
Код написан на ассемблере и решает задачу поиска слов, содержащих букву о
, и вывода этих слов вместе с их количеством.
Список действий:
- Получение хэндлов для консоли и клавиатуры.
- Запрос на ввод строки.
- Создание таблицы адресов начала и длины каждого слова в строке.
- Поиск в каждом слове символа
о
и вывод этого слова на консоль. - В конце программы выводится количество найденных слов.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д