LOCALS

.MODEL	SMALL


.CODE

PUBLIC	ByteToStr
PUBLIC	WordToStr
PUBLIC	DWordToStr
PUBLIC	ByteToHex
PUBLIC	StrLen
PUBLIC	MemSearch
PUBLIC	Delay
PUBLIC	Sound
PUBLIC	ReadKey

;*******************************************************************************
;ByteToStr	выполняет преобразование 8-битного беззнакового числа
;		в строку символов, заканчивающуюся нулем
;*******************************************************************************
;Использует:	нет
;
;Вызов:		AL = 8-битное беззнаковое число (N)
;		ES:DI -> буфер
;
;Возврат:	нет
;
;Изменяемые
;  регистры:	AX,BX,CX,DX,Flags
;*******************************************************************************
ByteToStr	PROC

		xor	ah,ah

;*******************************************************************************
;WordToStr	выполняет преобразование 16-битного беззнакового числа
;		в строку символов, заканчивающуюся нулем
;*******************************************************************************
;Использует:	нет
;
;Вызов:		AX = 16-битное беззнаковое число (N)
;		ES:DI -> буфер
;
;Возврат:	нет
;
;Изменяемые
;  регистры:	AX,BX,CX,DX,Flags
;*******************************************************************************
WordToStr:

		xor	dx,dx

;*******************************************************************************
;DWordToStr	выполняет преобразование 32-битного беззнакового числа
;		в строку символов, заканчивающуюся нулем
;*******************************************************************************
;Использует:	нет
;
;Вызов:		DX:AX = 32-битное беззнаковое число (N)
;		ES:DI -> буфер
;
;Возврат:	нет
;
;Изменяемые
;  регистры:	AX,BX,CX,DX,Flags
;*******************************************************************************
DWordToStr:

		push	si		;сохраняем регистры в стеке
		push	di

		mov	si,10		;SI = делитель на 10
		xor	cx,cx		;CX = счетчик цифр, помещенных в стек

@@Next_Digit:	push	ax
		mov	ax,dx
		xor	dx,dx
		div	si		;AX = старшее слово (N / 10)
					;DX = (старшее слово N) mod 10
		mov	bx,ax		;BX = старшее слово (N / 10)
		pop	ax		;AX = младшее слово N

		div	si		;AX = младшее слово (N / 10)
					;DX = N mod 10
		push	dx		;поместить одну цифру в стек

		mov	dx,bx		;DX = старшее слово (N / 10)

		inc	cx
		or	bx,ax		;N равно нулю?
		jnz	@@Next_Digit		

;берем цифры в обратном порядке, преобразуем в символы и помещаем в ОП

		cld

@@Store_Digit_Loop:
		pop	ax		;берем цифры в обратном порядке
		add	al,'0'		;преобразуем цифру в символ
		stosb
		loop	@@Store_Digit_Loop

		mov	BYTE PTR es:[di],0	;записываем 0 в конце строки

		pop	di		;восстанавливаем регистры
		pop	si

		ret

ByteToStr	ENDP

;*******************************************************************************
;ByteToHex	выполняет преобразование шестнадцатиричного числа в символьную
;		форму
;*******************************************************************************
;Использует:	нет
;
;Вызов:		AL = шестнадцатиричное число
;
;Возврат:	AX = число в символьной форме
;
;Изменяемые
;  регистры:	AX,Flags
;*******************************************************************************
ByteToHex	PROC

		aam	10h
		xchg	al,ah
		add	ax,'00'

		cmp	al,'9'
		jna	@@Second_Digit
		add	al,7

@@Second_Digit:	cmp	ah,'9'
		jna	@@Exit
		add	ah,7

@@Exit:		ret

ByteToHex	ENDP

;*******************************************************************************
;StrLen		определяет длину строки
;*******************************************************************************
;Использует:	нет
;
;Вызов:		DS:SI -> строка символов, заканчивающаяся нулем
;
;Возврат:	CX = число символов в строке (длина строки)
;
;Изменяемые
;  регистры:	AL,CX,Flags
;*******************************************************************************
StrLen		PROC

		push	es		;сохраняем регистры в стеке
		push	di

		push	ds
		pop	es
		mov	di,si		;ES:DI -> строка символов

		xor	al,al		;AL=0 (признак конца строки)
		mov	cx,0FFFFh
		cld
		repne	scasb
		not	cx
		dec	cx		;CX = длина строки

		pop	di		;восстанавливаем регистры
		pop	es
		ret

StrLen		ENDP

;*******************************************************************************
;MemSearch	осуществляет поиск в указанном диапозоне ячеек памяти
;		заданной последовательности байтов
;*******************************************************************************
;Использует:	нет
;
;Вызов:		ES:DI -> начало поиска
;		DS:SI -> искомая последовательность байтов
;		CX = длина области поиска
;		BX = длина искомой последовательности байтов (BX<=CX)
;
;Возврат:	ZF=0, если заданная последовательность байтов не найдена
;		ZF=1, если заданная последовательность байтов найдена:
;		      ES:DI -> найденная последовательность байтов
;
;Изменяемые
;  регистры:	DI,CX,DX,Flags
;*******************************************************************************
MemSearch	PROC

		mov	dx,di		;сохраняем смещение области поиска

		cld

@@Search_Loop:	push	si		;сохраняем в стеке смещение искомой
					;последовательности байтов
		push	di		;сохраняем в стеке текущее смещение
					;области поиска
		push	cx		;сохраняем в стеке значение счетчика
					;по области поиска

		mov	cx,bx		;CX = длина искомой последовательности
					;байтов
		repe	cmpsb		;осуществляем побайтовое сравнение

		pop	cx		;восстанавливаем счетчик по области
					;поиска
		pop	di		;восстанавливаем текущее смещение
					;области поиска
		pop	si		;DS:SI -> искомая последовательность
					;байтов

		je	@@Exit		;если совпали все байты, то выход

		dec	cx
		inc	di

		cmp	cx,bx		;длина оставшейся области поиска не меньше
					;длины искомой последовательности байтов?
		jnb	@@Search_Loop

		mov	di,dx		;восстанавливаем смещение области поиска

@@Exit:		ret

MemSearch	ENDP

;*******************************************************************************
;Delay		приостанавливает выполнение программы на указанное время
;*******************************************************************************
;Использует:	нет
;
;Вызов:		CX = время задержки в единицах, кратных 1/18,2 с
;
;Возврат:	нет
;
;Изменяемые
;  регистры:	AX,BX,Flags
;*******************************************************************************
Delay		PROC

		push	ds		;сохраняем DS в стеке

		mov	ax,40h
		mov	ds,ax		;DS = сегмент области данных ROM BIOS

		mov	bx,ds:[6Ch]	;BX = младшее слово первоначального
					;значения счетчика времени

@@Wait_Loop:	mov	ax,ds:[6Ch]	;AX = младшее слово текущего значения
					;счетчика времени
		sub	ax,bx		;AX = текущее время ожидания
		jnb	@@Compare

		neg	ax

@@Compare:	cmp	ax,cx		;цикл, пока текущее время ожидания
		jb	@@Wait_Loop	;меньше указанного

		pop	ds		;восстанавливаем DS

		ret

Delay		ENDP

;*******************************************************************************
;Sound		производит звуковой сигнал через встроенный динамик
;*******************************************************************************
;Использует:	Delay
;
;Вызов:		BX = частота звукового сигнала в герцах (> 18 Гц)
;		CX = длительность звучания сигнала в единицах, кратных 1/18,2 с
;
;Возврат:	нет
;
;Изменяемые
;  регистры:	AX,BX,DX,Flags
;*******************************************************************************
Sound		PROC

		mov	al,0B6h
		out	43h,al		;устанавливаем готовность таймера

		mov	dx,12h
		mov	ax,34DEh	;DX:AX = 1139182 (частота таймера)
		div	bx		;AX = счетчик для требуемой частоты

		out	42h,al		;загружаем младший байт
		jmp	SHORT $+2
		mov	al,ah
		out	42h,al		;загружаем старший байт

		in	al,61h		;считываем значение из порта 61h

		push	ax		;сохраняем в стеке исходное значение
					;управляющего порта

		or	al,3		;устанавливаем биты 0 и 1
					;(бит 0 управляет пульсацией динамика,
					;бит 1 управляет передачей выходного
					;сигнала таймера динамику)
		out	61h,al		;включаем динамик

		call	Delay		;ожидание в течение интервала
					;времени CX/18,2 с

		pop	ax		;восстанавливаем исходное значение
					;управляющего порта
		out	61h,al

		ret

Sound		ENDP

;*******************************************************************************
;ReadKey	считывает следующую нажатую клавишу
;*******************************************************************************
;Использует:	int 16h
;
;Вызов:		нет
;
;Возврат:	AL = код ASCII
;		AH = сканируемый код нажатой клавиши
;
;Изменяемые
;  регистры:	AX,Flags
;*******************************************************************************
ReadKey		PROC

		xor	ah,ah		;AH=0 (чтение следующего знака
					;клавиатуры)
		int	16h

		ret

ReadKey		ENDP


END
