Разбить заданную строку на две части - Assembler
Формулировка задачи:
добрый день
нужна программа, содержащая в себе подпрограмму, которая разбивает заданную строку на две части: первое слов (до первого пробела) и остальная часть строки (пробелы в начале строки убираются)
после выполнения программы все слова выводятся в консоль по отдельности
надыбал код не помню на каком сайте. проверил - работает. стал вникать в принципы ее реализации.. ии... всё )) ничего не понял
может кто-то намекнуть на правильные ответы для возникших вопросов?)
какой механизм использован в 16-17 строках?
мы вносим в bMax максимальное значение строки, а после туда же пишем строку, которую нам необходимо в будущем анализировать?
если так, то как мы получаем доступ к этой строке в процедуре, если название bMax после нигде не используется.
я, конечно, читал о структуре буфера. первый байт - максимальная длина строки, второй - фактическая, а с третьего идет сами данные.. как-то это взаимосвязано?)
Листинг программы
- .186 ;чтобы можно было использовать push <число>
- assume cs:code, ds:data, es:data
- SSEG segment stack ;сегмент стека
- db 400h dup (?)
- SSEG ends
- code segment para public 'code'
- start:
- mov ax, data
- mov ds, ax
- mov es, ax ;пусть es=ds=data
- lea dx, sString
- mov ah, 9
- int 21h ;ждем строку
- mov bMax, 80 ;задаем максимальное значение строки (в нулевом будет 80 - макс длина)
- lea dx, bMax ;в первом после ввода останется фактич длина, а со второй идут данные
- mov ah, 0ah
- int 21h ;вводим строку
- lea dx, sResult
- mov ah, 9
- int 21h ;выводим заголовок о выводе слов
- mov wAddr, offset bString ;адрес строки
- next:
- push offset wAddr ;адрес адреса строки
- call FirstWord ;разбиваем на подстроки
- test ax, ax ;ax = адресу слова, =0 - одни пробелы
- jz finish ;в конце пробелы - на выход
- mov dx, ax
- mov ah, 9
- int 21h ;выведем слово
- mov ah, 2 ;на новую строку
- mov dl, 0dh
- int 21h
- mov dl, 0ah
- int 21h
- cmp wAddr, 0 ;последнее слово?
- jne next ;продолжаем разбивать строку
- finish:
- lea dx, sPress
- mov ah, 9
- int 21h ;press any key
- mov ah, 8
- int 21h ;ждем any key
- mov ax, 4c00h
- int 21h ;bye
- ;Разбор строки на первое слово и все остальное
- ;Исходная строка портится! В конце слова ставится $ для вывода по 9 функции
- ;Параметр - адрес слова с адресом строки
- ;Возвращается в ax адрес первого слова, в слове с адресом строки
- ; возвращается адрес подстроки, начинающейся за первым словом или 0 для последнего слова
- ppStr equ [bp+4] ;адрес адреса строки
- FirstWord proc
- push bp
- mov bp, sp
- xor cx, cx ;адрес первого слова
- mov bx, ppStr ;адрес адреса строки
- mov si, [bx] ;адрес строки
- SearchBegin: ;цикл разбора строки
- lodsb ;очередной символ
- cmp al, 0dh ;конец строки
- je FW_last ;строка из одних пробелов
- cmp al, ' ' ;пробел?
- je SearchBegin ;первые пробелы обходим
- lea cx, [si-1] ;адрес начала слова
- SearchEnd: ;ищем конец слова
- lodsb ;очередной символ
- cmp al, 0dh ;конец строки
- je FW_last ;последнее слово
- cmp al, ' ' ;конец слова?
- jne SearchEnd ;ищем пробел после слова
- mov byte ptr [si-1], '$' ;поставим вместо пробела '$' для вывода
- jmp FW_ret ;на выход
- FW_last: ;последнее слово или одни пробелы
- mov byte ptr [si-1], '$' ;поставим вместо пробела '$' для вывода
- xor si, si ;больше слов нет
- FW_ret:
- mov [bx], si ;сохраним адрес второй подстроки или 0, если больше слов нет
- mov ax, cx ;возвращаем адрес первого слова для вывода
- pop bp
- ret 2 ;уберем из стека параметр
- FirstWord endp
- code ends
- data segment para public 'data'
- sString db 0ah,'Enter string: $'
- sResult db 0ah,0ah,'Words:',0dh,0ah,'$'
- sPress db 0dh,0ah,'Press any key$'
- ;буфер для ввода числовой строки (для функции 0ah)
- bMax db ? ;максимальный размер буфера
- bCount db ? ;реальный размер строки
- bString db 80 dup (?) ;сама строка
- wAddr dw ? ;адрес анализируемой строки
- data ends
- end start
Решение задачи: «Разбить заданную строку на две части»
textual
Листинг программы
- org 100h
- jmp start
- mes0 db 13,10,'String: $'
- mes1 db 13,10,' Words: $'
- bMax db 80 ; макс.размер буфера
- bLen db 0 ; длина строки
- bStr db 80 dup(0) ; буфер источника
- buff db 32 dup('$') ; буфер приёмника
- start:
- mov dx,mes0 ;
- call message ;
- mov ah,0Ah ; заполяем источник строкой юзера
- mov dx,bMax ;
- int 21h ;
- mov si,bStr ; адрес начала строки для LODSB
- printWord: ;
- call findSpace ; заполняем приёмный буфер
- cmp byte[buff],'$' ; буфер пустой?
- je printWord ;
- mov dx,mes1 ; в приёмнике что-то есть. мессага!
- call message ;
- mov dx,buff ; выводим данные из буфера
- call message ;
- jmp printWord ; ищем сл.слово в источнике
- stop: ;
- mov al,7 ; бипер..
- int 29h ;
- xor ax,ax ;
- int 16h ;
- int 20h ; выход!
- ;нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн
- message: ;===================================================
- mov ah,9 ;
- int 21h ;
- ret ;
- findSpace: ;=================================================
- mov cx,32 ; очистим приёмный буфер
- mov al,'$' ;
- mov di,buff ;
- push di ;
- rep stosb ;
- ;-----------------------;--
- pop di ;
- @1: lodsb ; читаем символ из SI
- cmp al,0Dh ; всю строку юзера проверили?
- je endStr ;
- cmp al,' ' ; пробел?
- je @2 ;
- stosb ; нет - сохраняем символ в приёмнике
- jmp @1 ; сл.символ..
- @2: ;
- ret ; выход из процедуры!
- endStr: ; выход из внешнего цикла!
- pop ax ; снимаем CALL'овский адрес возврата
- jmp stop ;
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д