Хостинг портала RFpro.ru: Московский хостер Профессиональный ХОСТИНГ на базе Linux x64 и Windows x64 РАССЫЛКИ ПОРТАЛА RFPRO.RU Лучшие эксперты данной рассылки Номер выпуска: | 1460 | Дата выхода: | 06.06.2011, 19:00 | Администратор рассылки: | Лысков Игорь Витальевич (Старший модератор) | Подписчиков / экспертов: | 214 / 63 | Вопросов / ответов: | 1 / 1 | Вопрос № 183472: Здравствуйте, уважаемые эксперты! Прошу вас ответить на следующий вопрос: помогите ,пожалуйста , написать программу, сообщающую о количестве строк в файле. Имя файла ввести с клавиатуры или передать как параметр командной строки. Чтение из файла орга... Вопрос № 183472: Здравствуйте, уважаемые эксперты! Прошу вас ответить на следующий вопрос: помогите ,пожалуйста , написать программу, сообщающую о количестве строк в файле. Имя файла ввести с клавиатуры или передать как параметр командной строки. Чтение из файла организовать блоком. Размер блока- по усмотрению. Желательны подробные комментарии. АСС-TASM. Заранее спасибо, с уважением Дмитрий. Отправлен: 01.06.2011, 18:38 Вопрос задал: Дмитрий (Посетитель) Всего ответов: 1 Страница вопроса » Отвечает Лысков Игорь Витальевич (Старший модератор) : Здравствуйте, Дмитрий! Для подсчета строк ищем и считаем код 0ah. Учитываем случай, когда в последней строке может и не быть кода 0ah. Программа сначала ищет имя файла, как параметр в командной строке, если не находит, то по запросу.
Код : .model small .stack 100h .code start: mov ax, @data mov es, ax ;настроим пока только регистр es ;ds равен сегменту PSP, там параметр командной строки call GetParm ;смотрим параметр из командной строки, если есть, ;то dx - смещение имени файла в сегменте данных mov ax, @data mov ds, ax ;настроим и ds jnc openFile ;если задано, то на открытие файла ;не задано - запрашиваем lea dx, sGetIn ;строка приглашения 'Enter file name:' call GetName ;ds:dx = адрес имени входного файла ;откроем входной файл openFile: mov ax, 3d00h ;открываем файл на чтение int 21h jc OpenError ;ошибка? mov bx, ax ;сохраним описатель файла в bx для дальнейшей работы xor si, si ;счетчик строк lea dx, buffer ;адрес буфера xor di, di ;для контроля файла 0 длины ;прочитаем readLoop: mov cx, 1000h ;будем читать 4к за 1 раз mov ah, 3fh ;функция чтения int 21h jc ReadError ;ошибка? mov cx, ax ;сохраним длину файла в cx jcxz lastRow ;чтение после конца даст 0 - признак, что все прочитано call CalcRows ;считаем строки кусочка jmp readLoop ;и на повтор lastRow: ;все прочитано, проверим случай, когда последняя строка ; не заканчивается на 0dh,0ah test di, di ;если файл был 0 длины, то di останется = 0, иначе jz printRows ; di содержит адрес за последним проанализированным куском cmp byte ptr [di-1], 0ah ;вот и проверим последний байт на 0ah je printRows ;равно - все учтено! inc si ;нет - учтем последнюю строку без кода конца строки! printRows: lea dx, sRows ;выведем сообщение mov ah, 9 int 21h mov ax, si ;число строк call PrintNum closeFile: mov ah, 3eh ;закроем входной файл int 21h PressAny: lea dx, sAny ;выведем 'Press any key' mov ah, 9 int 21h mov ah, 0 ; ждем нажатие на клавишу int 16h mov ax,4c00h ; конец работы int 21h ;обработка ошибок OpenError: ;ошибка открытия (файл или не найден, или занят) lea dx, sOpenErr mov ah, 9 int 21h jmp PressAny ;на вывод 'Press any key' ReadError: ;ошибка чтения lea dx, sReadErr mov ah, 9 int 21h jmp closeFile ;на закрытие и вывод 'Press any key' CalcRows proc ;подсчет строк, dx - адрес буфера, cx - длина, результат - si mov di, dx ;адрес начала буфера mov al, 0ah ;будем искать код 0ah calcLoop: jcxz calcRet ;длина 0 - нечего делать repne scasb ;ищем, пока не равно jne calcRet ;не равно, значит дошли до конца inc si ;равно - считаем jmp calcLoop ;по всему буферу calcRet: ret CalcRows endp ;Подпрограмма ввода имени файла ;на входе: ds:dx - адрес сообщения ;на выходе: ds:dx - адрес имени GetName proc mov ah, 9 ;выведем приглашение из dx:dx int 21h lea dx, buf ;введем строку mov ah, 0ah int 21h xor bx, bx ;заменим последний код 0dh на 0 mov bl, len ;длина введенной строки mov byte ptr string[bx], 0 ;пишем 0 lea dx, string ;возвращаем адрес имени ret GetName endp ;анализ параметра ;адрес параметра в PSP находится по адресу PSP:80h - длина, PSP:81h - сам параметр, ;заканчивающийся кодом 0dh. Мы длину трогать не будем, а будем анализировать по коду 0dh ;имя файла можно как предворять, так и завершать разделителями (пробелом, табуляцией) ;флагом CF = 0/1 вернем результат: задано/не задано имя файла GetParm proc mov si, 81h ;параметр в сегменте PSP lea di, string ;адрес в сегменте данных, куда запишем имя файла mov dx, di ;здесь вернем адрес имени, если задано, конечно xor cx, cx ;счетчик символов имени файла parmLoop: lodsb ;очередной cmp al, 0dh je endParm ;конец строки cmp al, ' ' je parmSeparator ;разделитель cmp al, 9 je parmSeparator ;разделитель stosb ;символ имени - копируем inc cx ;считаем jmp ParmLoop ;по всем parmSeparator: ;разделитель jcxz parmLoop ;разделители в начале строки пропускаем endParm: ;конец строки stc ;сначала пометим, что нет параметра jcxz parmRet ;счетчик символов нет - точно нет параметра mov al, 0 ;есть, завершаем строку нулем stosb clc ;и помечаем, что параметр задан parmRet: ret GetParm endp PrintNum proc ;вывод беззнакового числа из ax mov bx, 10 ;будем делить на 10 xor cx, cx ;счетчик цифр DivLoop: xor dx, dx ;готовимся к делению dx:ax / bx div bx ;ax - частное, dx - остаток=очередной младшей цифре push dx ;сохраним цифру в стеке inc cx ;посчитаем test ax, ax ;продолжим, пока не 0 jnz DivLoop mov ah, 2 ;функция вывода PrintLoop: ;будем выводить в обратном порядке, начиная со старшей шифры pop ax ;восстановим очередной разряд or al, '0' ;превратим в символ int 29h ;выведем loop PrintLoop ret PrintNum endp .data ;строки сообщений sGetIn db 0dh,0ah,'Enter file name: $' sRows db 0dh,0ah,'Rows count = $' sAny db 0dh,0ah,'Press any key$' sOpenErr db 0dh,0ah,'File open error!$' sReadErr db 0dh,0ah,'File read error!$' buf label byte ; буфер для приема строки с клавиатуры (по ф-и 0ah) max db 128 ; максимальная длина строки len db 0 ; реальная длина введенной строки string db 128 dup (?) ; сама строка buffer db 1000h dup(?) ;буфер для чтения файла end start ----- Люби своего ближнего, как самого себя Ответ отправил: Лысков Игорь Витальевич (Старший модератор) Ответ отправлен: 03.06.2011, 11:51 Номер ответа: 267559 Украина, Кировоград Тел.: +380957525051 ICQ # 234137952 Mail.ru-агент: igorlyskov@mail.ru Вам помог ответ? Пожалуйста, поблагодарите эксперта за это! Как сказать этому эксперту "спасибо"? | Отправить SMS #thank 267559 на номер 1151 (Россия) | Еще номера » | Оценить выпуск » Нам очень важно Ваше мнение об этом выпуске рассылки! Скажите "спасибо" эксперту, который помог Вам! Отправьте СМС-сообщение с тестом #thank НОМЕР_ОТВЕТА на короткий номер 1151 (Россия) Номер ответа и конкретный текст СМС указан внизу каждого ответа. Полный список номеров » * Стоимость одного СМС-сообщения от 7.15 руб. и зависит от оператора сотовой связи. (полный список тарифов) ** При ошибочном вводе номера ответа или текста #thank услуга считается оказанной, денежные средства не возвращаются. *** Сумма выплаты эксперту-автору ответа расчитывается из суммы перечислений на портал от биллинговой компании. |
Комментариев нет:
Отправить комментарий