Разбить заданную строку на две части - 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 ;