2.as2 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. ; ‚ à¨ ­â 19
  2. ; ‚¥àá¨ï 2. „ ­­ë¥ ¨§ ä ©«  2.txt
  3. ; …­¨ª¥¥¢ ˆ.�. 2084/1
  4. .286
  5. cseg segment byte public 'CODE'
  6. assume cs:cseg, ds:dseg, es:dseg
  7. start:
  8. mov ax, seg dseg
  9. mov es, ax
  10. mov ds, ax
  11. ;------------------------------
  12. mov ax, 3d00h
  13. mov dx, offset fname
  14. int 21h
  15. jnc $+5
  16. jmp no_file
  17. push ax
  18. mov bp, 1 ; BP will hold ifWORK
  19. line_loop:
  20. pop bx
  21. mov cx, 1
  22. mov dx, offset from
  23. char_loop:
  24. mov ah, 3fh
  25. int 21h
  26. mov si, dx
  27. test ax, ax
  28. jz eof
  29. cmp byte ptr ds:[si], 0ah
  30. je eol
  31. inc dx
  32. jmp char_loop
  33. eol: mov byte ptr ds:[si-1], 0
  34. push bx
  35. jmp work
  36. eof: mov byte ptr ds:[si], 0
  37. xor bp, bp
  38. mov ah, 3eh
  39. int 21h
  40. work:
  41. cmp byte ptr [from], 0 ; Test input string to non-empty
  42. jnz $+5
  43. jmp no_string
  44. mov di, offset to
  45. add di, [need_len]
  46. mov [max_len], di
  47. xor cx, cx ; Begin of work
  48. not cx
  49. mov di, offset from
  50. mov al, ' '
  51. repz scasb ; Skip all spaces at the beginning
  52. dec di
  53. mov real_ofs, di ; Save offset of first non-space character
  54. xor ax, ax
  55. xor cx, cx
  56. not cx
  57. repnz scasb ; Search for tailing zero
  58. dec di
  59. dec di ; di - points to last non-zero char
  60. not cx
  61. dec cx
  62. push cx ; Save full length of string
  63. std ; Change direction flag to backwards
  64. mov al, ' '
  65. xor cx, cx
  66. not cx
  67. repz scasb ; Search for non-space charecter at the end of string
  68. inc di
  69. inc di ; di points to next after last non-space
  70. mov byte ptr [di], 0 ; Discard tailing spaces
  71. not cx
  72. dec cx ; Get count of tailing spaces
  73. pop ax
  74. sub ax, cx ; Calculate length of trimmed string (without leading and tailing spaces)
  75. jg $+5 ; If length is positive - countinue work
  76. jmp no_string
  77. cld ; Restore normal direction flag
  78. mov cx, ax ; Set trimmed length
  79. mov di, real_ofs ; Set pointer to the beginng of string
  80. xor bx, bx ; bx holds non-space chars count
  81. xor dx, dx ; dx holds word count-1
  82. word_loop: ; loop for calculate word and non-space char count in sentence
  83. mov al, [di] ; get char from string
  84. test al, al ; test for EOS
  85. jz next_1 ; If so - we are reached end of string
  86. cmp al, ' ' ; Compare with space
  87. jz inloop1 ; if so - skip all following spaces and inc word count
  88. inc bx ; Increment letters count
  89. inc di ; advance pointer
  90. dec cx ; decrement residuary string length
  91. jnz word_loop ; if we got non-tested chars - continue loop
  92. jmp next_1 ; if not - end our loop
  93. inloop1: ; If we've found space in input string
  94. inc dx ; Increment word count
  95. inc cx ; Inc string's length for next line's right work
  96. repz scasb ; Skip all following spaces in input string
  97. dec di ; Adjust pointer to point to first non-space char
  98. jmp word_loop ; Countinue loop
  99. next_1: mov ax, need_len ; Get our required output string length
  100. sub ax, bx ; Decrease this length by total count of letters
  101. ; to get count of spaces, that we need to arrange
  102. ; between words
  103. cmp ax, dx ; if that count is less than spaces we've got to put
  104. ; betten words to save them separated then
  105. jge need_spaces ; Show error message
  106. mov toins, 1 ; We'll have to crop input string, so leave we'll
  107. ; only one space as gaps
  108. xor dx, dx ; And don't need for additional spaces
  109. jmp just_copy
  110. need_spaces:
  111. mov bx, dx ; bx will hold count of gaps between words
  112. test bx, bx ; if we've got only one word - so we don't need any gaps
  113. jz just_copy
  114. xor dx, dx ; clear dx for normal div's work
  115. div bx ; AX - holds count of spaces, bx - count of gaps, so
  116. mov toins, ax ; new ax - holds space count in each gap, and
  117. ; dx - remainder of division
  118. just_copy: ; Prepare of our main loop of creation of output string
  119. mov si, real_ofs ; Source - input string
  120. mov di, offset to ; Destination - memory to hold output string
  121. main_loop: ; Here comes the main loop
  122. cmp di, [max_len]
  123. jl $+4
  124. jmp wr_out
  125. mov al, [si] ; get character
  126. test al, al ; if we're reached end of string
  127. jz wr_out ; goto write output
  128. cmp al, ' ' ; if we got space -
  129. jz space ; work with this gap
  130. movsb ; else just copy character from input to output
  131. jmp main_loop ; continue loop
  132. space: ; if we've got space - skip all following in input
  133. ; and add needed space count in gap in output
  134. xor cx, cx
  135. not cx
  136. xchg si, di ; scas works with di - so we need to put si there
  137. repz scasb ; al - hold ' ' (by that reason we are here)
  138. dec di ; so we've skipped all following spaces in input
  139. xchg di, si ; return poiners at their normal state
  140. mov cx, toins ; put needed space count in output string
  141. rep stosb ; in al we're still got ' '
  142. test dx, dx ; if our remainder are zero
  143. jz main_loop ; - continue loop
  144. stosb ; else - put one more space in current gap
  145. dec dx ; and decrease remainder
  146. jmp main_loop ; and of course continue our loop
  147. wr_out: ; Now we're reached final touches to our prog
  148. mov byte ptr [di], 0
  149. xor ax, ax ; We're going to search for tailing null char
  150. ; (we could skip this line because the only way to get here
  151. ; is only from testing al to zero, so it DEFINITLY zero)
  152. mov di, offset to ; point to output string
  153. xor cx, cx ; Search for FFFF chars
  154. not cx ;
  155. repnz scasb ; Search tailing zero
  156. dec di ; And put
  157. mov al, '$' ; '$'
  158. stosb ; instead of it
  159. mov ah, 9 ; Use DOS's help
  160. mov dx, offset to ; to write output
  161. int 21h ; to user's eyes
  162. mov dx, offset newline
  163. int 21h
  164. outta:
  165. test bp, bp
  166. jz norm_out
  167. jmp line_loop; output is OK!
  168. bad_len:
  169. jmp short norm_out
  170. no_string:
  171. mov ah, 09h
  172. mov dx, offset newline
  173. int 21h
  174. jmp short outta
  175. no_file:
  176. mov ah, 09h
  177. mov dx, offset no_file_str
  178. int 21h
  179. jmp norm_out
  180. err_read:
  181. mov ah, 09h
  182. mov dx, offset err_read_str
  183. int 21h
  184. jmp norm_out
  185. norm_out:
  186. mov ah, 4ch
  187. int 21h
  188. ends
  189. dseg segment para public 'DATA'
  190. fname db '2.txt',0
  191. toins dw 0
  192. divis dw 0
  193. wordcnt dw 0
  194. need_len dw 100
  195. real_ofs dw 0
  196. max_len dw 0
  197. newline db 0dh, 0ah, '$'
  198. no_file_str db 'Couldn''t open file 2.txt$'
  199. err_read_str db 'Error while reading 2.txt$'
  200. dw 0 ; front border of string
  201. from db 200 dup (?)
  202. to db 100 dup (?)
  203. ends
  204. sseg segment stack
  205. db 200 dup (?)
  206. ends
  207. end start