; Вариант 19 ; Версия 2. Данные из файла 2.txt ; Еникеев И.Р. 2084/1 .286 cseg segment byte public 'CODE' assume cs:cseg, ds:dseg, es:dseg start: mov ax, seg dseg mov es, ax mov ds, ax ;------------------------------ mov ax, 3d00h mov dx, offset fname int 21h jnc $+5 jmp no_file push ax mov bp, 1 ; BP will hold ifWORK line_loop: pop bx mov cx, 1 mov dx, offset from char_loop: mov ah, 3fh int 21h mov si, dx test ax, ax jz eof cmp byte ptr ds:[si], 0ah je eol inc dx jmp char_loop eol: mov byte ptr ds:[si-1], 0 push bx jmp work eof: mov byte ptr ds:[si], 0 xor bp, bp mov ah, 3eh int 21h work: cmp byte ptr [from], 0 ; Test input string to non-empty jnz $+5 jmp no_string mov di, offset to add di, [need_len] mov [max_len], di xor cx, cx ; Begin of work not cx mov di, offset from mov al, ' ' repz scasb ; Skip all spaces at the beginning dec di mov real_ofs, di ; Save offset of first non-space character xor ax, ax xor cx, cx not cx repnz scasb ; Search for tailing zero dec di dec di ; di - points to last non-zero char not cx dec cx push cx ; Save full length of string std ; Change direction flag to backwards mov al, ' ' xor cx, cx not cx repz scasb ; Search for non-space charecter at the end of string inc di inc di ; di points to next after last non-space mov byte ptr [di], 0 ; Discard tailing spaces not cx dec cx ; Get count of tailing spaces pop ax sub ax, cx ; Calculate length of trimmed string (without leading and tailing spaces) jg $+5 ; If length is positive - countinue work jmp no_string cld ; Restore normal direction flag mov cx, ax ; Set trimmed length mov di, real_ofs ; Set pointer to the beginng of string xor bx, bx ; bx holds non-space chars count xor dx, dx ; dx holds word count-1 word_loop: ; loop for calculate word and non-space char count in sentence mov al, [di] ; get char from string test al, al ; test for EOS jz next_1 ; If so - we are reached end of string cmp al, ' ' ; Compare with space jz inloop1 ; if so - skip all following spaces and inc word count inc bx ; Increment letters count inc di ; advance pointer dec cx ; decrement residuary string length jnz word_loop ; if we got non-tested chars - continue loop jmp next_1 ; if not - end our loop inloop1: ; If we've found space in input string inc dx ; Increment word count inc cx ; Inc string's length for next line's right work repz scasb ; Skip all following spaces in input string dec di ; Adjust pointer to point to first non-space char jmp word_loop ; Countinue loop next_1: mov ax, need_len ; Get our required output string length sub ax, bx ; Decrease this length by total count of letters ; to get count of spaces, that we need to arrange ; between words cmp ax, dx ; if that count is less than spaces we've got to put ; betten words to save them separated then jge need_spaces ; Show error message mov toins, 1 ; We'll have to crop input string, so leave we'll ; only one space as gaps xor dx, dx ; And don't need for additional spaces jmp just_copy need_spaces: mov bx, dx ; bx will hold count of gaps between words test bx, bx ; if we've got only one word - so we don't need any gaps jz just_copy xor dx, dx ; clear dx for normal div's work div bx ; AX - holds count of spaces, bx - count of gaps, so mov toins, ax ; new ax - holds space count in each gap, and ; dx - remainder of division just_copy: ; Prepare of our main loop of creation of output string mov si, real_ofs ; Source - input string mov di, offset to ; Destination - memory to hold output string main_loop: ; Here comes the main loop cmp di, [max_len] jl $+4 jmp wr_out mov al, [si] ; get character test al, al ; if we're reached end of string jz wr_out ; goto write output cmp al, ' ' ; if we got space - jz space ; work with this gap movsb ; else just copy character from input to output jmp main_loop ; continue loop space: ; if we've got space - skip all following in input ; and add needed space count in gap in output xor cx, cx not cx xchg si, di ; scas works with di - so we need to put si there repz scasb ; al - hold ' ' (by that reason we are here) dec di ; so we've skipped all following spaces in input xchg di, si ; return poiners at their normal state mov cx, toins ; put needed space count in output string rep stosb ; in al we're still got ' ' test dx, dx ; if our remainder are zero jz main_loop ; - continue loop stosb ; else - put one more space in current gap dec dx ; and decrease remainder jmp main_loop ; and of course continue our loop wr_out: ; Now we're reached final touches to our prog mov byte ptr [di], 0 xor ax, ax ; We're going to search for tailing null char ; (we could skip this line because the only way to get here ; is only from testing al to zero, so it DEFINITLY zero) mov di, offset to ; point to output string xor cx, cx ; Search for FFFF chars not cx ; repnz scasb ; Search tailing zero dec di ; And put mov al, '$' ; '$' stosb ; instead of it mov ah, 9 ; Use DOS's help mov dx, offset to ; to write output int 21h ; to user's eyes mov dx, offset newline int 21h outta: test bp, bp jz norm_out jmp line_loop; output is OK! bad_len: jmp short norm_out no_string: mov ah, 09h mov dx, offset newline int 21h jmp short outta no_file: mov ah, 09h mov dx, offset no_file_str int 21h jmp norm_out err_read: mov ah, 09h mov dx, offset err_read_str int 21h jmp norm_out norm_out: mov ah, 4ch int 21h db 0EFFFh dup (?) ends dseg segment para public 'DATA' fname db '2.txt',0 toins dw 0 divis dw 0 wordcnt dw 0 need_len dw 100 real_ofs dw 0 max_len dw 0 newline db 0dh, 0ah, '$' db 0EFFFh dup (?) no_file_str db 'Couldn''t open file 2.txt$' err_read_str db 'Error while reading 2.txt$' dw 0 ; front border of string from db 200 dup (?) to db 100 dup (?) ends sseg segment stack db 200 dup (?) ends end start