Учебник по ассемблеру (ASM)
 

Ассемблер в примерах - Ввод строки с клавиатуры, подсчет слов и определение разделителя

Вопрос:
Ввести с клавиатуры строку. Посчитать количество слов в строке. Определить, что является разделителем слов. Вывести результаты на экран.

Ответ:
Программа в приложении считает слова и определяет все возможные разделители Определяем символы, которые могут быть частью слова (лат, рус, цифры) Все остальные - разделители
	.model	tiny
	.data

sin	db	'Enter string:  $'
sWCnt	db	0dh,0ah,'Words count = '
sNum	db	8 dup (0)	;сюда запишем число слов
sSep	db	'Separators: $'	;разделители
sPress	db	0dh,0ah,'Press any key$'

buf	label	byte		; буфер для приема строки с клавиатуры (по ф-и 0ah)
max	db	128		; максимальная длина строки
len	db	0		; реальная длина введенной строки

	.data?
string	db	128 dup (?)	; сама строка (сегмент data? идет следом за data)
sSepar	db	64 dup (?)	; здесь сохраним разделители

	.code
	.startup

	lea	dx, sin
	mov	ah, 9
	int	21h		; приглашение ввести строку

	lea	dx, buf
	mov	ah, 0ah
	int	21h		; вводим строку

	xor	bx, bx		; bh - флаг наличия слова, bl - число слов
	xor	dx, dx		; dx - число найденных разделителей
	lea	si, string	; сама строка
main_loop:			; основной цикл
	lodsb			; очередной символ
	cmp	al, 0dh		; конец строки ?
	je	print_rezult	; на конец обработки

	cmp	al, '0'		; цифры ?
	jb	separ_found	; меньше - разделитель
	cmp	al, '9'
	jbe	word_found	; часть слова

	cmp	al, 'A'		; большие латинские ?
	jb	separ_found	; меньше - разделитель
	cmp	al, 'Z'
	jbe	word_found	; часть слова

	cmp	al, 'a'		; малые латинские ?
	jb	separ_found	; меньше - разделитель
	cmp	al, 'z'
	jbe	word_found	; часть слова

	cmp	al, 80h		; кириллица А-п
	jb	separ_found	; меньше - разделитель
	cmp	al, 0afh
	jbe	word_found	; часть слова

	cmp	al, 0e0h	; кириллица р-я,Ё,ё,украинские,белорусские буковки
	jb	separ_found	; меньше - разделитель
	cmp	al, 0f7h
	jbe	word_found	; часть слова

separ_found:			; найден разделитель
	cmp	bh, 0		; было ли перед этим слово
	je	cmp_separ	; если не было, то на обработку разделителя
	mov	bh, 0		; сбросим флаг слова
	inc	bl		; увеличим счетчик слов
cmp_separ:			; проверим, был ли такой раньше
	mov	cx, dx		; счетчик найденных разделителей
	lea	di, sSepar	; строка найденных разделителей
	jcxz	set_separ	; если еще не было, то сразу запоминем
	repne	scasb		; ищем
	je	next		; если нашли, то на чтение следующего символа
				; иначе, di указывает на конец строки
set_separ:
	stosb			; запоминаем в конце строки
	inc	dx		; и увеличиваем счетчик
next:
	jmp	main_loop	; на основной цикл

word_found:			; слово
	mov	bh, 1		; установим флаг
	jmp	next		; на чтение очередного символа

print_rezult:			; встретили конец строки
	add	bl, bh		; посчитаем самое последнее слово (если оно есть)

;преобразуем число слов в строку
	mov	al, bl		; число слов
	lea	di, sNum	; адрес строки
	call	itoa		; преобразуем

	push	dx		; сохраним счетчик разделителей
	lea	dx, sWCnt
	mov	ah, 9
	int	21h		; выведем число слов

	lea	dx, sSep
	mov	ah, 9
	int	21h		; разделители

	mov	al,'"'
	int	29h		; в кавычках (чтобы было видно пробел)
	lea	si, sSepar	; адрес стоки
	pop	cx		; число разделителей (бывший dx)
pr_separ_loop:
	lodsb
	int	29h
	loop	pr_separ_loop

	mov	al,'"'
	int	29h

	lea	dx, sPress
	mov	ah, 9
	int	21h

	mov	ah, 0
	int	16h		; чтобы сразу не убегало с экрана

	mov	ax, 4c00h
	int	21h

itoa	proc			; преобразование числа из al в строку
	xor	cx, cx		; счетчик цифр
	mov	bl, 10		; будем делить на 10
div_loop:
	mov	ah, 0		; сбросим предыдущий остаток
	div	bl		; делим ax/bl
	push	ax		; сохраним остаток ah в стеке
	inc	cx		; посчитаем
	cmp	al, 0		; делим, пока al не 0
	jnz	div_loop
pr_loop:			; цикл вывода
	pop	ax		; восстановим из стека очередную цифру
	mov	al, ah		; в al
	or	al, '0'		; сделаем из числа символ
	stosb			; запишем по адресу [di++]
	loop	pr_loop
	mov	ax, 0a0dh	; перевод строки
	stosw
	mov	al, '$'		; для 9 функции
	stosb
	ret
itoa	endp
	end


   Вперёд
   Содержание
Бу поддоны купить с доставкой в Липецке