< -->

;fchss.asm
;Заменяет в файле строку на строку из такого же количества символов
	.model tiny
	.code
	.386
	org 100h

FREAD	equ	0F800h	;32768 байт
start:
	mov	al, 254
	mov	byte ptr strbufflen, al
	mov	byte ptr strbufflen_, al
	mov	byte ptr _strbufflen, al

	mov	dx, offset message
	mov	ah, 9
	int	21h

	mov	dx, offset _strbufflen
	mov	ah, 0Ah
	int	21h

	mov	dx, offset EOL
	mov	ah, 9
	int	21h

	xor	bx, bx
	mov	bl, byte ptr _strlen
	mov	byte ptr _strbuff[bx], 0

	mov	ax, 3D23h	;Открыть файл: чтение/запись/
				;все операции для других процессов запрещены
	mov	dx, offset _strbuff
	mov	cl, 00100111b;атрибуты - арх, сист, скрыт, тдч
	int	21h

	jc	error_exit
	mov	idfile, ax

	mov	dx, offset mess1
	mov	ah, 9
	int	21h

	mov	dx, offset strbufflen
	mov	ah, 0Ah
	int	21h

	mov	dx, offset EOL
	mov	ah, 9
	int	21h

	mov	dx, offset mess2
	mov	ah, 9
	int	21h

	mov	dx, offset strbufflen_
	mov	ah, 0Ah
	int	21h

	mov	dx, offset EOL
	mov	ah, 9
	int	21h

	xor	ax, ax
	mov	al, strlen

	test	al, al
	jnz	next_check

	push	ax
	mov	ah, 9
	mov	dx, offset error_lsz
	int	21h
	pop	ax
	inc	ah
	
next_check:
	cmp	al, byte ptr strlen_
	je	processing

	mov	ah, 9
	mov	dx, offset error_nes
	int	21h
	jmp	closefilenexit

processing:
	test	ah, ah
	jnz	closefilenexit

	mov	ax, 5B10h
				;все операции для других процессов запрещены
	mov	dx, offset tmpfile
	mov	cx, 0000000000100000b;атрибуты - арх
	int	21h

	mov	tmpidfile, ax

	mov	ax, 4200h
	xor	cx, cx
	xor	dx, dx
	mov	dl, strlen
	mov	bx, idfile
	int	21h

read_loop:
	mov	ax, 4201h
	xor	cx, cx
	xor	dx, dx
	mov	cl, strlen
	sub	dx, cx
	mov	cx, 0FFFFh
	mov	bx, idfile
	int	21h

	mov	ah, 3Fh		;читаем файл
	mov	bx, idfile
	mov	cx, FREAD
	mov	dx, offset filebuffer
	int	21h
	jc	closeallnexit
	mov	flen, ax
	push	ax
	call	findings
	call	writetmp
	pop	ax
	cmp	ax, FREAD
	je	read_loop
closeallnexit:
	mov	bx, tmpidfile
	mov	ah, 3Eh
	int	21h
	mov	bx, idfile	;закрываем файлы
	mov	ah, 3Eh
	int	21h

	;удаляем старый
	mov	ah, 41h
	mov	dx, offset _strbuff
	int	21h

	;переименовываем tmp в old
	mov	ah, 56h
	mov	dx, offset tmpfile	;старое имя
	mov	di, offset _strbuff	;новое имя
	int	21h

	jmp	short	exit_prog

closefilenexit:
	mov	bx, idfile	;закрываем файл
	mov	ah, 3Eh
	int	21h
	jmp	short	exit_prog

error_exit:
	push	ax
	mov	dx, offset error_msg
	mov	ah, 9
	int	21h
	pop	ax

	mov	dx, offset error_fnf
	cmp	ax, 02h
	je	pne

	mov	dx, offset error_pnf
	cmp	ax, 03h
	je	pne

	mov	dx, offset error_ftm
	cmp	ax, 04h
	je	pne

	mov	dx, offset error_acd
	cmp	ax, 05h
	je	pne

	mov	dx, offset error_uid
	cmp	ax, 06h
	je	pne

	mov	dx, offset error_bam
	cmp	ax, 0Ch
	je	pne

	mov	dx, offset EOL

pne:
	mov	ah, 9
	int	21h
exit_prog:
	ret

findings	proc	near	; Процедура ищет подстроку в строке
	;(все её вхождения) и заменяет её на другую строку

	mov	di, offset filebuffer 	;буфер с содержимым файла
	dec	di		;потом увеличится на 1
	push	di
	xor	cx, cx

	cld       	;флаг направления
new_iter:
	pop	di	;смещаемся в буфере для сравнения с искомой строкой
	inc	di		;со следующего байта
	mov	si, offset strbuff	;искомая строка
	push	di		;сохраняем для последующего использования
	mov	cl, strlen	;длина подстроки, возвращается ещё DOS
	repe	cmpsb		;сравниваем до первого различия
	jcxz	copy_str	;если вся длина строки вышла - переходим
				;на процедуру копирования
		;{неэффективен при строках длиной 1 и 2 байта, т.к. cx
		;становится равным 0}
lbd:	;лабуда...
	sub	di, offset filebuffer	;это конец буфера, или нет?
	cmp	di, flen
	jne	new_iter		;нет - сравниваем дальше
	jmp	short exit_procedure	;иначе - выходим
copy_str:
	jne	short	lbd	;если после сравнивания последние байты
				;не равны - то выходим
				;из подпрограммы копирования
	push	si		;сохранить - изменится
	mov	cl, strlen	;длина копируемой строки
	sub	di, cx		;положение в буфере для заменяемой строки
	mov	si, offset strbuff_	;смещение копируемой строки
	rep	movsb	;копируем
	pop	si		;восстанавливаем регистр
	jmp	short	lbd
exit_procedure:			;выходим, извлекая из стека ненужное слово
	pop	di		;оставшееся там после сохранения di

	ret
findings	endp

writetmp	proc	near

	mov	ah, 40h
	mov	bx, tmpidfile
	mov	cx, flen
	mov	dx, offset filebuffer
	int	21h

	mov	ax, 4201h
	xor	cx, cx
	xor	dx, dx
	mov	cl, strlen
	sub	dx, cx
	mov	cx, 0FFFFh
	mov	bx, tmpidfile
	int	21h

	ret
writetmp	endp

tmpfile		db	"fchs.tmp", 0
message		db	"Введите имя файла: ","$"
mess1		db	"Введите строку для поиска: ","$"
mess2		db	"Введите строку для замены: ","$"
error_msg	db	"Ошибка при открытии файла: ", "$"
error_fnf	db	"Файл не найден",0Ah, 0Dh, "$"
error_pnf	db	"Путь не найден",0Ah, 0Dh, "$"
error_ftm	db	"Слишком много открытых файлов",0Ah, 0Dh, "$"
error_acd	db	"Доступ запрещён",0Ah, 0Dh, "$"
error_bam	db	"Неправильный режим доступа",0Ah, 0Dh, "$"
error_uid	db	"Неправильный идентификатор файла",0Ah, 0Dh, "$"
error_frw	db	"Ошибка чтения/записи из/в файл(а)", 0Ah, 0Dh, "$"
error_nes	db	"Строки различны по длине!", 0Ah, 0Dh, "$"
error_lsz	db	"Строка для поиска пуста!"
EOL		db	0Ah, 0Dh, "$"
flen		dw	?
idfile		dw	?
tmpidfile	dw	?

_strbufflen	db	?
_strlen		db	?
_strbuff	db	254 dup (?)

strbufflen	db	?
strlen		db	?
strbuff		db	254 dup (?)

strbufflen_	db	?
strlen_		db	?
strbuff_	db	254 dup (?)
filebuffer:
	end start

Назад