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

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


Хостинг портала RFpro.ru:
Московский хостер
Профессиональный ХОСТИНГ на базе Linux x64 и Windows x64

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

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

Boriss
Статус: Академик
Рейтинг: 2623
∙ повысить рейтинг »
Абаянцев Юрий Леонидович aka Ayl
Статус: Профессионал
Рейтинг: 2279
∙ повысить рейтинг »
vladisslav
Статус: 8-й класс
Рейтинг: 1318
∙ повысить рейтинг »

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

Номер выпуска:1408
Дата выхода:27.12.2010, 10:30
Администратор рассылки:Лысков Игорь Витальевич (Старший модератор)
Подписчиков / экспертов:224 / 68
Вопросов / ответов:1 / 1

Вопрос № 181458: Здравствуйте, уважаемые эксперты! Прошу Вас ответить на следующий вопрос: "Работа с файлами.Пользователь вводит с клавиатуры имя файла с текстом и имя создаваемого файла, в который будет помещен результат. Слова в строке могут быть разделены ...



Вопрос № 181458:

Здравствуйте, уважаемые эксперты! Прошу Вас ответить на следующий вопрос:
"Работа с файлами.Пользователь вводит с клавиатуры имя файла с текстом и имя создаваемого файла, в который будет помещен результат. Слова в строке могут быть разделены пробелами и знаками препинания. Отсортировать строки файла по длинам"
Тип памяти любой.
Написание Tasm. (32 бита). (работа внутри тасма. тоесть через ctrl+f8)

Отправлен: 19.12.2010, 20:13
Вопрос задал: Ирина (Посетитель)
Всего ответов: 1
Страница вопроса »


Отвечает Лысков Игорь Витальевич (Старший модератор) :
Здравствуйте, Ирина !
Вот Вам программа, которая сортирует указанный файл (< 64к)
Код:
;Пользователь вводит с клавиатуры имя файла с текстом
и имя создаваемого файла, 
;в который будет помещен результат. Слова в строке могут быть разделены пробелами
;и знаками препинания. Отсортировать строки файла по длинам
.model tiny
.code
.startup
;Определим место для данных за программой
;Для этого сначала ограничим стек 100h и разместим его сразу программой
lea ax, last ;последний исползованный адрес
and ax, 0fffeh ;сделаем кратным 2
add ax, 100h ;добавим место под стек
mov s p, ax ;вершина стека
;Теперь определим сегмент данных
add ax, 0fh ;чтобы выровнять с избытком до параграфа (10h)
shr ax, 4 ;длина программы+стека в параграфах
mov cx, ds ;сегмент программы
add ax, cx ;ax - сегмент за стеком - для данных
mov segData, ax ;сораним
;и сегмент индексов
add ax, 1000h ;размер сегмента данных - 64к
mov segIdx, ax ;за ним разместим сегмент индексов

lea dx, sEnterIn ;строка приглашения ввести имя входного файла
call GetName ;вводим имя входного файла, результат - в dx
jc Finish ;если пустая строка, то выходим

mov ax, 3d00h ;открываем на чтение
int 21h
jc OpenError ;не найдено - выводим сообщение и выходим
mov bx, ax ;handle файла
push ds ;сохраним сегмент данных программы
mov ax, segData
mov ds, ax ;сегмент данных файла
xor dx, dx ;начальный адрес
mov cx, 0fffdh ;максимальная возможная длина
; (2 байта резерва на возможный до бавочный
; последний eol)
mov ah, 3fh ;функция чтения
int 21h
jc ReadError ;если ошибка, то выводим сообщение и выходим
mov si, ax ;длина файла
cmp word ptr [si-2], 0a0dh ;проверим, есть ли в конце код конца строки
je EolFound ;есть, ну и отлично
mov word ptr [si], 0a0dh ;добавим 0d0a
add ax, 2 ;и увеличим длину на 2
EolFound:
pop ds ;восстановим сегмент данных программы
mov FileLen, ax ;сохраним длину файла
mov ah, 3eh ;закрываем файл
int 21h

call FormIdx ;Сформируем индексы в сегменте индексов

call Sort ;Отсортируем индексы

lea dx, sEnterOut ;строка приглашения ввести имя выходного файла
call GetName ;вводим имя выходного файла, результат - в dx
jc Finish ;если пустая строка, то выходим

mov ah, 3ch ;создаем выходной файл
xor cx, cx ;без атрибутов
int 21h
jc CreateError ;ошибка - на выход
mov bx, ax ;handle

call FormOut ;выводим в отсортированном порядке
pushf
mov ah, 3eh ;закрываем файл
int 21h
popf
jc WriteError

Finish: ;все сделано...
lea dx, sPress ;выведем приглашение нажать на любую клавишу
mov ah, 9
int 21h

mov ah, 0 ;ждем клавишу
int 16h

mov ax, 4c00h
int 21h ;выход в ДОС

;Сообщения об ошибках
OpenError:
lea dx, sOpenError
jmp PrintStr
ReadError:
pop ds ;т.к. регистр ds был в стеке
lea dx, sReadError
jmp PrintStr
CreateError:
lea dx, sCreateError
jmp PrintStr
WriteError:
lea dx, sWriteError
PrintStr: ;выводим сообщение
mov ah, 9
int 21h
jmp Finish

GetName proc ;Вводим строку с именем
mov ah, 9
int 21h ;приглашение на ввод имени входного файла

mov bNum, 80 ;максимальный размер буфера для ввода строки
lea dx, bNum
mov ah, 0ah
int 21h ;вводим строку

;отсечем лидирующие пробелы
lea si, sName ;введенная строка
GNStart:
lodsb ;очередной символ
cmp al, ' '
je GNStart ;пробелы пропускаем
cmp al, 0d h
je GNError ;если пустая строка или пробелы, то взведем FC
lea dx, [si-1] ;есть начало строки, имени файла
GNEnd: ;найдем конец имени - пробел или код 0dh
lodsb ;очередной символ
cmp al, 0dh
je EndFound ;конец строки
cmp al, ' ' ;и пробел - нашли конец имени
jne GNEnd ;иначе продолжаем искать
EndFound:
mov byte ptr [si-1], 0 ;вставим 0 в конце имени
clc ;есть имя файла
ret
GNError:
stc ;пустая строка
ret
GetName endp

FormIdx proc ;формирование массива индексов
push ds es ;будем менять сегментные регистры
mov cx, FileLen ;длина данных
mov es, segData ;сегмент данных
mov ds, segIdx ;сегмент индексов
xor di, di ;адрес в сегменте данных
xor si, si ;адрес в сегменте индексов
mov al, 0dh ;будем искать код 0dh
FormIdxLoop: ;цикл по всем символам
jcxz FormIdxRet ;cx=0 в конце данных
mov bx, di ;запомним начало строки
repne s casb ;ищем конец строки, который есть обязательно
; (мы в случае необходимости добавили в конец 0d0a)
mov dx, di ;адрес конца строки + 1
sub dx, bx ;длина строки + 1
dec dx ;ровно длина строки
mov [si], bx ;сохраняем адрес начала строки
mov [si+2], dx ;и длину строки (без 0d0a)
add si, 4 ;на следующую запись индекса
inc di ;пройдем код 0ah
dec cx ;уменьшим для него счетчик символов
jmp FormIdxLoop ;пока не пройдем все данные файла
FormIdxRet:
shr si, 2 ;si - число строк файла!
pop es ds
mov Rows, si ;запомним число строк файла
ret
FormIdx endp

Sort proc ;отсортируем индексы методом пузырька
push ds
mov cx, Rows ;число строк (записей)
mov ds, segIdx ;сегмент индексов

cmp cx, 2 ;0 и 1 нет смысла сортировать
jb SortRet
dec cx ;число сравнений
xor si, si ;адрес индекса
SortLoop: ;цикл по поиску очередного минимального
lea di, [si+4] ;начинаем со следующего
push cx ;сохраним счетчик
mov ax, [si+2] ;текущий минимальный по адресу [si]
SearchMinLoop: ;цикл по всем последующим
;сравниваем текущий со всеми последующими
cmp ax, [di+2] ;если текущий минимальный <= последующего,
jle SortNext ; то обходим обмен
;меняем местами элементы
mov ax, [si] ;меняем местами адреса строк
xchg ax, [di]
mov [si], ax
mov ax, [si+2] ;меняем местами длины строк
xchg ax, [di+2]
mov [si+2], ax ;по адресу [si+2] и в ax новая минимальная длина
SortNext:
add di, 4 ;на следующий последующий
loop SearchMinLoop
add si, 4 ;на следующий текущий
pop cx ;восстановим счетчик сравнений
loop SortLoop

SortRet:
pop ds
ret
Sort endp

FormOut proc ;выводим в файл все строки в отсорт виде
push ds es
mov cx, Rows ;число строк
mov es, segIdx ;сегмент индексов
mov ds, segData ;сегмент данных
xor si, si ;адрес индекса
WriteLinesLoop: ;по всем строкам
push cx ;сохраним счетчик строк
mov dx, es:[si] ;адрес строки
mov cx, es:[si+2] ;длина строки
add cx, 2 ;+ 2 байта 0d0a
mov ah, 40h
int 21h ;пишем в файл
pop cx ;воостановим счетчик строк
jc FormOutRet ;ксли ошибка, то FC = 1
add si, 4 ;на след индекс
loop WriteLinesLoop
clc ;все ок
FormOutRet:
pop es ds
ret
FormOut endp

.data
sEnterIn db 'Enter input file name: $'
sEnterOut db 0ah,'Enter output file name: $'
sPress db 0ah,'Press any key$'
sOpenError db 0ah,'Open Error',0dh,'$'
sReadError db 0ah,'Read Error',0dh,'$'
sCreateError db 0ah,'Create Error',0dh,'$'
sWriteError db 0ah,'Write Error',0dh,'$'

.data?
segData dw ? ;сегмент данных
segIdx dw ? ;сегмент индексов
FileLen dw ? ;длина файла
Rows dw ? ;число строк
< br>;буфер для ввода числовой строки (для функции 0ah)
bNum db ? ;максимальный размер буфера
bCount db ? ;реальный размер строки
sName db 80 dup (?) ;сама строка

Last label byte ;последний использованный адрес

end

-----
Люби своего ближнего, как самого себя

Ответ отправил: Лысков Игорь Витальевич (Старший модератор)
Ответ отправлен: 26.12.2010, 00:55
Номер ответа: 265079
Украина, Кировоград
Тел.: +380957525051
ICQ # 234137952
Mail.ru-агент: igorlyskov@mail.ru

Вам помог ответ? Пожалуйста, поблагодарите эксперта за это!
Как сказать этому эксперту "спасибо"?
  • Отправить SMS #thank 265079 на номер 1151 (Россия) | Еще номера »
  • Отправить WebMoney:


  • Оценить выпуск »
    Нам очень важно Ваше мнение об этом выпуске рассылки!

    Задать вопрос экспертам этой рассылки »

    Скажите "спасибо" эксперту, который помог Вам!

    Отправьте СМС-сообщение с тестом #thank НОМЕР_ОТВЕТА
    на короткий номер 1151 (Россия)

    Номер ответа и конкретный текст СМС указан внизу каждого ответа.

    Полный список номеров »

    * Стоимость одного СМС-сообщения от 7.15 руб. и зависит от оператора сотовой связи. (полный список тарифов)
    ** При ошибочном вводе номера ответа или текста #thank услуга считается оказанной, денежные средства не возвращаются.
    *** Сумма выплаты эксперту-автору ответа расчитывается из суммы перечислений на портал от биллинговой компании.


    © 2001-2010, Портал RFPRO.RU, Россия
    Авторское право: ООО "Мастер-Эксперт Про"
    Автор: Калашников О.А. | Программирование: Гладенюк А.Г.
    Хостинг: Компания "Московский хостер"
    Версия системы: 2010.6.25 от 13.12.2010

    В избранное