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

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


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

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

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

Boriss
Статус: Академик
Рейтинг: 2673
∙ повысить рейтинг »
Жерар
Статус: Профессор
Рейтинг: 2423
∙ повысить рейтинг »
Абаянцев Юрий Леонидович aka Ayl
Статус: Профессионал
Рейтинг: 2240
∙ повысить рейтинг »

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

Номер выпуска: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 (Россия) | Еще номера »
  • Отправить WebMoney:


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

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

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

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

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

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

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



    В избранное