Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

RFpro.ru: Ассемблер? Это просто! Учимся программировать


РАССЫЛКИ ПОРТАЛА RFPRO.RU

Лучшие эксперты по данной тематике

Коцюрбенко Алексей aka Жерар
Статус: Советник
Рейтинг: 2975
∙ повысить рейтинг »
Асмик Гаряка
Статус: Советник
Рейтинг: 27
∙ повысить рейтинг »
Куликов Роман Евгеньевич
Статус: 1-й класс
Рейтинг: 0
∙ повысить рейтинг »

/ КОМПЬЮТЕРЫ И СОФТ / Программирование / Assembler (Ассемблер)

Номер выпуска:1577
Дата выхода:24.12.2015, 17:21
Администратор рассылки:Лысков Игорь Витальевич (Старший модератор)
Подписчиков / экспертов:17 / 7
Вопросов / ответов:1 / 1

Консультация # 188427: Здравствуйте! У меня возникли сложности с таким вопросом: smile нужно вывести на экран имена файлов на дискете в порядке увеличения их размера это EXE - программа, ввод с клавиатуры средствами BIOS, вывод на экран в графическом режиме Динамическое распред...

Консультация # 188427:

Здравствуйте! У меня возникли сложности с таким вопросом: smile
нужно вывести на экран имена файлов на дискете в порядке увеличения их размера
это EXE - программа, ввод с клавиатуры средствами BIOS, вывод на экран в графическом режиме
Динамическое распределение памяти: освободить лишнюю память.

Хоть что-то можете подсказать?(

Дата отправки: 14.12.2015, 16:49
Вопрос задал: muhaeva.elza (Посетитель)
Всего ответов: 1
Страница онлайн-консультации »


Консультирует Лысков Игорь Витальевич (Старший модератор):

Здравствуйте, muhaeva.elza!
Держите программу.
В ней много разных интересных моментов, например, использование структур,
а особенно, реализация сортировки... Изучайте, вникайте...
Будут вопросы - спрашивайте. Но программа достаточно неочевидная,
без самостоятельного скурпулезного разбора у Вас ничего не получится!

Код (Assembler):
TITLE FAIL(EXE)
assume CS:code, DS:data

;некоторые структуры для удобства адресации данных
_dta			struc			;ДТА
dta_res		db	21 dup(?)		;резерв
dta_attr		db	?			;атрибут файла
dta_time		dw	?			;время файла
dta_date		dw	?			;дата файла
dta_size_lo	dw	?			;младшее слово длины файла
dta_size_hi	dw	?			;старшее слово длины файла
dta_name		db	13 dup (?)	;имя файла ASCIIZ, заканчивающееся 0
_dta			ends

;структура, описывающая элемент для хранения найденного 
;имени файла, его длины, а также поле, используемое для сортировки
_files		struc			
files_name	db	13 dup (?)	;имя файла ASCIIZ
files_size_lo	dw	?			;младшее слово длины файла
files_size_hi	dw	?			;старшее слово длины файла
files_pointer	dw	?			;указатель на структуру _files
_files		ends

;структура, описывающая элемент для печати строки
_print		struc
print_pos		dw	?			;позиция курсора, low - колонка, high - строка
print_pstr	dw	?			;указатель на строку ASCIIZ
_print		ends

; описываем сегмент кода
code segment
PROGRAM_START:	; метка точки входа программы

; настройка регистра DS
mov AX, data
mov DS, AX

; освобождение памяти 
mov AX, abcd			; сегментный адрес конца программы
mov DX, ES			; сегментный адрес начала программы
sub AX, DX			; размер программы в параграфах
mov BX, AX			; оставим его в BX
mov AH, 4ah			; функция изменения размера блока
int 21h

mov	ax, 000dh			;переходим в графический режим 320х200
int	10h

lea	si, directory		;адрес буфера для имени текущей директории
call	GetDir			;сформируем имя текущей директории

lea	di, text			;адрес массива, задающего набор строк для вывода
call	print_text		;выводим текст на экран

call	FindFiles			;ищем все файлы в текущей директории
call	SortFiles			;сортируем по возрастанию длины файла
call	PrintFiles		;выводим на экран

mov	ah, 0
int	16h

mov	ax, 0003h			;возвращаемся в текстовый режим
int	10h

mov ax, 4c00h
INT 21h 				;вызов прерывание окончания работы программы

;вывод массива текста на экран
;параметр: di - адрес массива _print
print_text	proc	near
	mov	dx, [_print ptr di].print_pos	;строка, колонка
	cmp	dx, -1						;дошли до конца?
	je	print_text_ret
	mov	si, [_print ptr di].print_pstr	;адрес строки
	call	print_str						;выводим с указанной позиции
	add	di, size _print				;на следующий элемент массива структур
	jmp	print_text

print_text_ret:
	ret
print_text	endp

;вывод строки [si] с указанной [dx] позиции
print_str	proc	near
	mov	ah, 2
	xor	bx, bx
	int	10h				;позиция курсора
		
print_str_loop:
	lodsb
	cmp	al, 0			;строка заканчивается нулем
	je	print_str_ret
	mov	ah, 0eh			;функция выводит в текущей позиции курсора и
						;автоматически смещает курсор на 1 вправо
	mov	bl, 0eh			;атрибут
	int	10h
	jmp	print_str_loop

print_str_ret:
	ret
print_str	endp

;получаем имя полного пути текущей директории в [si]
GetDir	proc	near
	mov	ah, 19h			;текущий диск, 0 - А
	int	21h
	add	al, 'A'			;делаем из номера букву
	mov	[si], al
	mov	ax,'\:'			;отделяем <диск>:/
	mov	word ptr [si+1], ax
	add	si,3				;на позицию собственно имени директории
	mov	ah, 47h			;функция получения имени полного пути текущей директории
	mov	dl,0				;текущего диска
	int	21h
	ret
GetDir	endp

;поиск всех файлов и заполнение массива структур _files 
FindFiles	proc	near
	lea	dx, dta			;зададим область DTA, необходимую для поиска
	mov	ah, 1ah
	int	21h

	lea	di, files			;адрес массива _files
	xor	bp, bp			;счетчик файлов

	lea	dx, spec			;маска файлов "*.*"
	mov	cx, 0			;атрибут файлов, которые ищем
	mov	ah,4eh			;начало поиска
search_loop:
	int	21h
	jc	f_end			;ищем, пока ищется. В конце будет С=1 и АХ=12h
						;возможны другие ошибки, но мы их для простоты 
						;проверять не будем, даже 12h. Выходим из поиска по С=1
	lea	si,dta.dta_name	;адрес имени файла в ДТА
						;копируем в элемент массива _files
	xor	bx,bx			;будем индексировать с помощью bx 
copy_name_loop:
	lodsb
	mov	[_files ptr di+bx].files_name, al
	inc	bx
	cmp	al,0				;копируем, включая завершающий 0
	jne	copy_name_loop
						;копируем длину файла
	mov	ax, word ptr dta.dta_size_lo
	mov	[_files ptr di].files_size_lo,ax	
	mov	ax, word ptr dta.dta_size_hi
	mov	[_files ptr di].files_size_hi,ax	
	mov	[_files ptr di].files_pointer,di
	
	add	di,size _files		;на следующий элемент _files
	inc	bp				;считаем

	mov	ah,4fh			;продолжение поиска, dx не должен портиться!
	jmp	search_loop
f_end:
	mov	cx,bp			;возвращаем в СХ количество найденных файлов
	ret
FindFiles	endp

;Сортировка массива files по увеличению длины файла
;Используется сортировка "пузырьком"
;Чтобы меньше менять местами, введено поле указателя,
;которое и будет меняться местами 
SortFiles	proc	near
	lea	si,files			;адрес массива
						;найдем адрес последнего элемента массива
						;будем по нему определять конец массива
	mov	ax,size _files		;размер элемента массива
	mul	cx				;умножаем на их количество
	add	ax,offset files - size _files	;минус размер одного
	mov	dx,ax			;dx - адрес последнего элемента массива

Sort_loop1:				;цикл по первому указателю
	lea	di,[si+size _files]	;второй начинается со следующего
Sort_loop2:				;цикл по второму указателю
	cmp	di,dx			;второй дошел до конца массива?
	ja	Sort_next1		;если да, то на увеличение первого указателя
	mov	bx,[_files ptr si].files_pointer	;получаем укзатели на элементы
	mov	bp,[_files ptr di].files_pointer
										;и сравниваем длины файлов
	mov	ax,ds:[_files ptr bp].files_size_hi	;сначала старшее слово
	cmp	ax,[_files ptr bx].files_size_hi		;сравнение беззнаковое!
	jb	Sort_change		;если второй меньше первого, то меняем местами
	ja	Sort_next2		;если больше, то на увеличение второго указателя
	mov	ax,ds:[_files ptr bp].files_size_lo	;если равно, то сравниваем младшее слово
	cmp	ax,[_files ptr bx].files_size_lo
	jae	Sort_next2		;если больше или равно, то на увеличение второго указателя
Sort_change:				;меняем местати
	mov	ax,[_files ptr di].files_pointer		;указатели в массиве
	xchg	ax,[_files ptr si].files_pointer
	mov	[_files ptr di].files_pointer,ax
	xchg	bx,bp							;и в регистрах
Sort_next2:
	add	di,size _files						;второй указатель - на следующий элемент
	jmp	Sort_loop2
Sort_next1:
	add	si,size _files		;увеличиваем первый указатель
	cmp	si,dx			;дошли до последнего?
	jb	Sort_loop1		;нет - продолжаем
	ret
SortFiles	endp

;вывод имен файлов с их длинами
;cx - количество элементов массива
;выводим только столько, сколько помещается на экран, не более 17
PrintFiles	proc	near
	lea	si,files			;адрес массива files
	mov	bp,0804h			;начальная позиция курсора
	cmp	cx,17			;проверим количество
	jle	print_names_loop
	mov	cx,17
print_names_loop:
	mov	dx,bp			;позиция для очередного элемента
	push	si				;сохраним адрес элемента массива
	mov	si,[_files ptr si].files_pointer	;адрес отсортированного элемента массива
	push	si				;сохраним его
	call	print_str			;выводим имя файла
	pop	si				;вернем адрес элемента массива
	mov	ax,[_files ptr si].files_size_lo	;длина файла
	mov	dx,[_files ptr si].files_size_hi
	call	PrintLen			;преобразуем число в строку и выведем
	pop	si				;вернем адрес в неотсортированном массиве
	add	si,size _files		;на следующий элемент
	add	bp,0100h			;смещаемся на строку ниже
	loop	print_names_loop
	ret
PrintFiles	endp

;вывод числа dx:ax в виде строки
;строка выравнивается по правому краю
;подпрограмма корректно выведет число до 655350000
PrintLen	proc	near
	push	cx				;сохраним счетчик элементов
	lea	di,number			;адрес буфера для строки-числа
	mov	si,di			;запомним для вывода
	mov	cx,'  '			;очистим 14 байт пробелами
	mov	[di],cx
	mov	[di+2],cx
	mov	[di+4],cx
	mov	[di+6],cx
	mov	[di+8],cx
	mov	[di+10],cx
	mov	[di+12],cx
	mov	byte ptr [di+15],0	;закроем строку нулем
	add	di,14			;на адрес последнего символа
						;заполнять будем от младшего к старшему
	mov	cx,10000			;разделим сначала на 10000
						;сразу делить на 10 нельзя!
						;может дать ошибку для больших чисел
	div	cx
	mov	cx,10			;дальше будем делить на 10
	test	ax,ax			;число больше 10000?
	jne	big_number		;да, сначала выведем младшие 4 разряда
	mov	ax, dx			;<10000 - выводим число заведомо меньшее 10000
	jmp	small_number
big_number:				;выводим ровно 4 младшие цифры
	push	ax				;сохраним частное для дальнейшего вывода
	mov	ax,dx			;выводим остаток (4 младшие цифры)
	xor	dx,dx
	div	cx
	or	dl,'0'
	mov	[di],dl			;единицы
	dec	di
	xor	dx,dx
	div	cx
	or	dl,'0'
	mov	[di],dl			;десятки
	dec	di
	xor	dx,dx
	div	cx
	or	dl,'0'
	mov	[di],dl			;сотни
	dec	di
	or	al,'0'
	mov	[di],al			;тысячи
	dec	di
	pop	ax
small_number:				;выводим столько разрядов, сколько есть
	xor	dx,dx
	div	cx
	or	dl,'0'
	mov	[di],dl			;очередной разряд
	dec	di
	test	ax,ax
	jne	small_number		;пока есть что-то

	mov	dx,bp			;позиция вывода
	add	dx,15			;вправо на 15 колонок
	call	print_str			;выводим строку-число на экран
	pop	cx
	ret
PrintLen	endp

code ends				;конец сегмента кода

; описание сегмента данных (переменные)
data segment
;массив для вывода кста на экран
text		_print	<0011h,cout1>	
		_print	<0104h,cout2>
		_print	<020ch,cout3>
		_print	<0308h,cout4>
		_print	<040fh,cout5>
		_print	<050ah,cout6>
		_print	<0604h,directory>
		_print	<-1>				;признак конца массива
COUT1	DB "Rabota",0
COUT2	DB "Sistemnoe programnoe obespecenie",0
COUT3	DB "Studenta gruppi ",0
COUT4	DB "FIO",0
COUT5	DB "Variant #4",0
COUT6	db "Spisok failov v papke:",0
spec		db "*.*",0				;маска для поиска файлов
number	db 16 dup(?)				;буфер для преобразования числа в строку
directory	db 64 dup(?)				;буфер для имени текущей директории
dta		_DTA	<>					;область ДТА для поиска
files	_files 1000 dup(<>)			;массив для хранения найденных имен файлов и их длин
								;максимально - 1000 штук  smile  
data ends

; описываем сегмент стека
stk segment stack
	dw 256 dup (?)	; выделяем под стек 256 слов
stk ends

abcd segment 'endseg'	; фиктивный сегмент для определения размера программы
abcd ends
	end PROGRAM_START	; конец программы

Консультировал: Лысков Игорь Витальевич (Старший модератор)
Дата отправки: 19.12.2015, 21:58
Рейтинг ответа:

НЕ одобряю +2 одобряю!


Оценить выпуск | Задать вопрос экспертам

главная страница  |  стать участником  |  получить консультацию
техническая поддержка  |  восстановить логин/пароль

Дорогой читатель!
Команда портала RFPRO.RU благодарит Вас за то, что Вы пользуетесь нашими услугами. Вы только что прочли очередной выпуск рассылки. Мы старались. Пожалуйста, оцените его. Если совет помог Вам, если Вам понравился ответ, Вы можете поблагодарить автора - для этого в каждом ответе есть специальные ссылки. Вы можете оставить отзыв о работе портале. Нам очень важно знать Ваше мнение. Вы можете поближе познакомиться с жизнью портала, посетив наш форум, почитав журнал, который издают наши эксперты. Если у Вас есть желание помочь людям, поделиться своими знаниями, Вы можете зарегистрироваться экспертом. Заходите - у нас интересно!
МЫ РАБОТАЕМ ДЛЯ ВАС!


В избранное