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

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


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

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

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

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

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

Номер выпуска:1466
Дата выхода:27.06.2011, 09:30
Администратор рассылки:Лысков Игорь Витальевич (Старший модератор)
Подписчиков / экспертов:205 / 65
Вопросов / ответов:1 / 1

Вопрос № 183693: Здравствуйте, уважаемые эксперты! Прошу вас ответить на следующий вопрос: вывести на экран последнюю строку из текстового файла. Дополнительные условия: DOS, TASM, COM-программа. Приложил код (не мой). В нем чтение и отображение на экран тек...



Вопрос № 183693:

Здравствуйте, уважаемые эксперты! Прошу вас ответить на следующий вопрос:
вывести на экран последнюю строку из текстового файла.
Дополнительные условия: DOS, TASM, COM-программа.
Приложил код (не мой). В нем чтение и отображение на экран текстового файла целиком.

Есть свои соображения по поводу алгоритма. Проблема в их реализации.
Открывается файл на чтение (уже есть).
Начинается чтение файла построчно (функцией BIOS или DOS)? (при чтении каждый символ копируется в переменную зарезервированную для строки).
Если символ не конец строки и не перевод каретки, то копирование продолжается. Если так, то идет проверка на EOF. Если EOF не найден после 0dh,0ah, то строка заново переписывается символами, прочитанными из следующей строки.
Если символ EOF, то последняя строка найдена (она в памяти и уже содержит прочитанные символы). Переход на вывод строки.
Конец программы.

Прошу дополнить приложенный код.

PS В коде не понятны несколько с трок:

Код :
mov cx,ax
        mov ah,40h
        xchg bp,bx
        int 21h
        xchg bp,bx

Конкретнее, на счет регистров bp,bx. Разъясните подробнее, пожалуйста.

Отправлен: 22.06.2011, 09:12
Вопрос задал: Ханинёв Пётр Валерьевич (1-й класс)
Всего ответов: 1
Страница вопроса »


Отвечает Лысков Игорь Витальевич (Старший модератор) :
Здравствуйте, Ханинёв Пётр Валерьевич!

Я считаю, что для решения поставленной задачи читать весь файл, пробегать его по всем строкам
только для того, чтобы найти последнюю строку нет никакого резона. Гораздо проще, сразу
"встать" в конец файла и тут же определиться с последней строкой.
А посему, предлагаю Вам такой алгоритм.
Читаем последние максимум 256 байт и уже в них ищем с конца последнюю строку

Отвечу на поставленные вопросы:
1) Прерывание 21h - это ДОС.
2) В языке ассемблера невозможно читать из файла построчно.
Можно только прочитать кусок файла в буфер и самому там анализировать.
3) Что Вы понимаете под EOF? Если спецсимвол, то да, есть такой, его код 1ah.
Но! Он практически не используется! Поэтому анализировать на него нет смысла.
Обычно под EOF понимают ситуацию, когда нечего уже читать...
(В программе, как Вы поняли сделано по-другому)
В дан ной программе я сделал анализ на код 1ah, но только для того, чтобы его
исключить при выводе на экран. Кроме него, сделан анализ на код перевода страницы, для той же цели.

По поводу регистров BP и BX Вам уже ответили в мини-форуме...

Код :
;вывести на экран последнюю строку из текстового файла.

 .model TINY
 .code
 org 100h

Entry:
 mov ax, 3D00h  ;открываем файл на чтение (al=0)
 mov dx, offset file_name ;имя файла
 int 21h
 jc open_error  ;проверка на ошибку
 mov bx, ax   ;описатель файла

 mov ax, 4202h  ;установим указатель на позицию от конца файла
 mov dx, -100h  ;cx:dx = -100h, т.е. 100h назад от конца
 mov cx, -1
 int 21h   ;если файл меньше, чем 100h, то указатель останется
     ; на начале файла!

 mov cx, 100h  ;читаем максимум 100h (ровно последние)
 mov ah, 3Fh   ;ф-я чтения
 mov dx, offset buffer ;буфер для чтения
 int 21h
 jc read_error  ;проверка на ошибку

 mov cx, ax   ;реальная длина прочитанного фрагмента

 mov ah, 3Eh   ;файл закрываем
 int 21h
     ;найдем начало последней строки
     ;будем искать код 0ah
 mov di, dx   ;адрес начала буфера
 add di, cx   ;на адрес за буфером
what_last:    ;проверим последние байты:
     ;символы "конец файла" (ctrl-Z = SUB = 1ah) и
     ;"перевод страницы" (ctrl-L = FF = 0ch) отсекаем,
     ;"перевод строки" (ctrl-J = LF = 0ah) пропускаем,
     ;ищем предыдущий
 jcxz zero_file  ;если длина = 0, то выведем сообщение
 dec di   ;на адрес последнего байта
 mov al, [di]  ;читаем его
 cmp al, 0ah   ;перевод строки?
 je EOL_found
 cmp al, 1ah   ;конец файла?
 je EOF_found
 cmp al, 0ch   ;перевод страницы?
 jne search_begin  ;нет - на поиск начала последней строки
EOF_found:    ;встретили код конца файла или перевод страницы
 dec cx   ;уменьшим длину буфера, тем самым исключим из вывода
 jmp what_last  ;продолжим анализ
EOL_found:    ;конец строки
 dec di   ;уменьшим указатель, т.о. обойдем его
search_begin:    ;ищем код 0ah в обратном направлении
 std    ;взведем флаг обратного направления
 push cx   ;сохраним длину буфера
 mov al, 0ah   ;код для поиска
 repne scasb   ;ищем cx раз, пока не равно
 pop cx   ;восстановим длину буфера
 cld    ;установим прямое направление
 jne for_first  ;если не равно, то имеем только одну строку 
     ;и надо только компенсировать результат scasb
 inc di   ;если равно, то надо обойти коды 0dh и 0ah
for_first:
 inc di   ;scasb проскакивает на 1 позицию дальше

 add cx, offset buffer ;cx = адресу за буфером
 sub cx, di   ;cx = длине строки

     ;строка найдена, ее адрес в di, длина в cx - выводим
 mov al, 0   ;код возврата
out_string:    ;вывод строки на стандартное устройство вывода (bx = 1)
 push ax   ;сохраним код возврата
 mov dx, di   ;адрес начала строки
 mov bx, 1   ;описатель устройства - на экран
 mov ah, 40h   ;ф-я записи
 int 21h

 pop ax   ;восстановим код возврата
 mov ah, 4Ch   ;выход в ДОС
 int 21h

;обработка ошибок
zero_file:    ;нулевой файл
 lea di, s_zero_error ;адрес сообщения
 mov cx, len_s_zero_error ;длина
 mov al, 1   ;код возврата
 jmp out_string  ;на вывод

open_error:    ;ошибка открытия файла
 lea di, s_open_error ;адрес сообщения 
 mov cx, len_s_open_error ;длина
 mov al, 2   ;код возврата
 jmp out_string  ;на вывод
read_error:
 lea di, s_read_error ;адрес сообщения
 mov cx, len_s_read_error ;длина
 mov al, 3   ;код возврата
 jmp out_string  ;на вывод

 .data      ;сегмент инициализированных данных
file_name  db "_file.txt",0  ;имя файла
s_zero_error  db "Zero file"
len_s_zero_error equ $-s_open_error  ;длина строки
s_open_error  db "File open error"
len_s_open_error equ $-s_open_error
s_read_error  db "File read error"
len_s_read_error equ $-s_read_error

 .data?      ;сегмент неинициализированных данных 
buffer db 256 dup (?)    ;буфер для чтения "хвоста" файла

 END Entry

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

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

Оценка ответа: 5
Комментарий к оценке:
Оптимальный вариант решения задачи. Подробные комментарии.

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


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

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

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

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

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

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

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



    В избранное