Разбить заданную строку на две части - Assembler

Узнай цену своей работы

Формулировка задачи:

добрый день нужна программа, содержащая в себе подпрограмму, которая разбивает заданную строку на две части: первое слов (до первого пробела) и остальная часть строки (пробелы в начале строки убираются) после выполнения программы все слова выводятся в консоль по отдельности надыбал код не помню на каком сайте. проверил - работает. стал вникать в принципы ее реализации.. ии... всё )) ничего не понял может кто-то намекнуть на правильные ответы для возникших вопросов?)
.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
какой механизм использован в 16-17 строках? мы вносим в bMax максимальное значение строки, а после туда же пишем строку, которую нам необходимо в будущем анализировать? если так, то как мы получаем доступ к этой строке в процедуре, если название bMax после нигде не используется. я, конечно, читал о структуре буфера. первый байт - максимальная длина строки, второй - фактическая, а с третьего идет сами данные.. как-то это взаимосвязано?)

Решение задачи: «Разбить заданную строку на две части»

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          ;

Оцени полезность:

6   голосов , оценка 3.833 из 5
Похожие ответы